blob: df865e997d384c13307c75123230764d5c48f175 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peng Fanfcdbde72018-01-10 13:20:37 +08002/*
Gaurav Jain2cddfcb2022-03-24 11:50:27 +05303 * Copyright 2017-2019, 2021 NXP
Peng Fanfcdbde72018-01-10 13:20:37 +08004 *
5 * Peng Fan <peng.fan@nxp.com>
Peng Fanfcdbde72018-01-10 13:20:37 +08006 */
7
8#include <common.h>
Simon Glass9edefc22019-11-14 12:57:37 -07009#include <cpu_func.h>
Simon Glass7fe32b32022-03-04 08:43:05 -070010#include <event.h>
Simon Glass691d7192020-05-10 11:40:02 -060011#include <init.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060012#include <log.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080013#include <asm/arch/imx-regs.h>
Simon Glass401d1c42020-10-30 21:38:53 -060014#include <asm/global_data.h>
Peng Fanfcdbde72018-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 Fan2f3c9202020-07-09 13:39:26 +080021#include <asm/ptrace.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080022#include <asm/armv8/mmu.h>
Peng Fane663c702019-08-27 06:25:58 +000023#include <dm/uclass.h>
Gaurav Jain2cddfcb2022-03-24 11:50:27 +053024#include <dm/device.h>
Peng Fan2f3c9202020-07-09 13:39:26 +080025#include <efi_loader.h>
Ye Li2707faf2019-07-15 01:16:46 -070026#include <env.h>
27#include <env_internal.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080028#include <errno.h>
29#include <fdt_support.h>
30#include <fsl_wdog.h>
31#include <imx_sip.h>
Simon Glasscd93d622020-05-10 11:40:13 -060032#include <linux/bitops.h>
Peng Fanfcdbde72018-01-10 13:20:37 +080033
34DECLARE_GLOBAL_DATA_PTR;
35
Stefano Babicd714a752019-09-20 08:47:53 +020036#if defined(CONFIG_IMX_HAB)
Peng Fanfcdbde72018-01-10 13:20:37 +080037struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
38 .bank = 1,
39 .word = 3,
40};
41#endif
42
43int timer_init(void)
44{
45#ifdef CONFIG_SPL_BUILD
46 struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
47 unsigned long freq = readl(&sctr->cntfid0);
48
49 /* Update with accurate clock frequency */
50 asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
51
52 clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
53 SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
54#endif
55
56 gd->arch.tbl = 0;
57 gd->arch.tbu = 0;
58
59 return 0;
60}
61
62void enable_tzc380(void)
63{
64 struct iomuxc_gpr_base_regs *gpr =
65 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
66
67 /* Enable TZASC and lock setting */
68 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
69 setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
Andrey Zhizhikin1289ff72022-01-24 21:48:09 +010070
71 /*
72 * According to TRM, TZASC_ID_SWAP_BYPASS should be set in
73 * order to avoid AXI Bus errors when GPU is in use
74 */
Peng Fana1d675a2022-04-29 16:18:49 +080075 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS);
Andrey Zhizhikin1289ff72022-01-24 21:48:09 +010076
77 /*
78 * imx8mn and imx8mp implements the lock bit for
79 * TZASC_ID_SWAP_BYPASS, enable it to lock settings
80 */
Peng Fana1d675a2022-04-29 16:18:49 +080081 setbits_le32(&gpr->gpr[10], GPR_TZASC_ID_SWAP_BYPASS_LOCK);
Andrey Zhizhikin1289ff72022-01-24 21:48:09 +010082
Ye Lib3cf0a82019-08-27 06:25:34 +000083 /*
84 * set Region 0 attribute to allow secure and non-secure
85 * read/write permission. Found some masters like usb dwc3
86 * controllers can't work with secure memory.
87 */
88 writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
Peng Fanfcdbde72018-01-10 13:20:37 +080089}
90
91void set_wdog_reset(struct wdog_regs *wdog)
92{
93 /*
94 * Output WDOG_B signal to reset external pmic or POR_B decided by
95 * the board design. Without external reset, the peripherals/DDR/
96 * PMIC are not reset, that may cause system working abnormal.
97 * WDZST bit is write-once only bit. Align this bit in kernel,
98 * otherwise kernel code will have no chance to set this bit.
99 */
100 setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
101}
102
Marek Vasut1434f932022-12-22 01:46:40 +0100103#ifdef CONFIG_ARMV8_PSCI
104#define PTE_MAP_NS PTE_BLOCK_NS
105#else
106#define PTE_MAP_NS 0
107#endif
108
Peng Fanfcdbde72018-01-10 13:20:37 +0800109static struct mm_region imx8m_mem_map[] = {
110 {
111 /* ROM */
112 .virt = 0x0UL,
113 .phys = 0x0UL,
114 .size = 0x100000UL,
115 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
116 PTE_BLOCK_OUTER_SHARE
117 }, {
Gary Bissoncb158852018-11-14 17:55:28 +0100118 /* CAAM */
119 .virt = 0x100000UL,
120 .phys = 0x100000UL,
121 .size = 0x8000UL,
122 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
123 PTE_BLOCK_NON_SHARE |
124 PTE_BLOCK_PXN | PTE_BLOCK_UXN
125 }, {
Marek Vasut09d86ea2021-02-25 21:52:26 +0100126 /* OCRAM_S */
127 .virt = 0x180000UL,
128 .phys = 0x180000UL,
129 .size = 0x8000UL,
130 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut1434f932022-12-22 01:46:40 +0100131 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Marek Vasut09d86ea2021-02-25 21:52:26 +0100132 }, {
Gary Bissoncb158852018-11-14 17:55:28 +0100133 /* TCM */
134 .virt = 0x7C0000UL,
135 .phys = 0x7C0000UL,
136 .size = 0x80000UL,
137 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
138 PTE_BLOCK_NON_SHARE |
Marek Vasut1434f932022-12-22 01:46:40 +0100139 PTE_BLOCK_PXN | PTE_BLOCK_UXN | PTE_MAP_NS
Gary Bissoncb158852018-11-14 17:55:28 +0100140 }, {
Peng Fanfcdbde72018-01-10 13:20:37 +0800141 /* OCRAM */
142 .virt = 0x900000UL,
143 .phys = 0x900000UL,
144 .size = 0x200000UL,
145 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut1434f932022-12-22 01:46:40 +0100146 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fanfcdbde72018-01-10 13:20:37 +0800147 }, {
148 /* AIPS */
149 .virt = 0xB00000UL,
150 .phys = 0xB00000UL,
151 .size = 0x3f500000UL,
152 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
153 PTE_BLOCK_NON_SHARE |
154 PTE_BLOCK_PXN | PTE_BLOCK_UXN
155 }, {
156 /* DRAM1 */
157 .virt = 0x40000000UL,
158 .phys = 0x40000000UL,
Peng Fan59efa6b2019-08-27 06:25:27 +0000159 .size = PHYS_SDRAM_SIZE,
Peng Fanfcdbde72018-01-10 13:20:37 +0800160 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut1434f932022-12-22 01:46:40 +0100161 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fan59efa6b2019-08-27 06:25:27 +0000162#ifdef PHYS_SDRAM_2_SIZE
Peng Fanfcdbde72018-01-10 13:20:37 +0800163 }, {
164 /* DRAM2 */
165 .virt = 0x100000000UL,
166 .phys = 0x100000000UL,
Peng Fan59efa6b2019-08-27 06:25:27 +0000167 .size = PHYS_SDRAM_2_SIZE,
Peng Fanfcdbde72018-01-10 13:20:37 +0800168 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
Marek Vasut1434f932022-12-22 01:46:40 +0100169 PTE_BLOCK_OUTER_SHARE | PTE_MAP_NS
Peng Fan59efa6b2019-08-27 06:25:27 +0000170#endif
Peng Fanfcdbde72018-01-10 13:20:37 +0800171 }, {
Peng Fan3c417282020-07-09 15:26:06 +0800172 /* empty entrie to split table entry 5 if needed when TEEs are used */
173 0,
174 }, {
Peng Fanfcdbde72018-01-10 13:20:37 +0800175 /* List terminator */
176 0,
177 }
178};
179
180struct mm_region *mem_map = imx8m_mem_map;
181
Marek Vasut076dc922021-02-27 14:59:00 +0100182static unsigned int imx8m_find_dram_entry_in_mem_map(void)
183{
184 int i;
185
186 for (i = 0; i < ARRAY_SIZE(imx8m_mem_map); i++)
Tom Riniaa6e94d2022-11-16 13:10:37 -0500187 if (imx8m_mem_map[i].phys == CFG_SYS_SDRAM_BASE)
Marek Vasut076dc922021-02-27 14:59:00 +0100188 return i;
189
190 hang(); /* Entry not found, this must never happen. */
191}
192
Peng Fan59efa6b2019-08-27 06:25:27 +0000193void enable_caches(void)
194{
Ye Li1c9bc0f2022-04-07 15:55:56 +0800195 /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch
196 * If OPTEE does not run, still update the MMU table according to dram banks structure
197 * to set correct dram size from board_phys_sdram_size
198 */
199 int i = 0;
200 /*
201 * please make sure that entry initial value matches
202 * imx8m_mem_map for DRAM1
203 */
204 int entry = imx8m_find_dram_entry_in_mem_map();
205 u64 attrs = imx8m_mem_map[entry].attrs;
Peng Fan3c417282020-07-09 15:26:06 +0800206
Ye Li1c9bc0f2022-04-07 15:55:56 +0800207 while (i < CONFIG_NR_DRAM_BANKS &&
208 entry < ARRAY_SIZE(imx8m_mem_map)) {
209 if (gd->bd->bi_dram[i].start == 0)
210 break;
211 imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
212 imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
213 imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
214 imx8m_mem_map[entry].attrs = attrs;
215 debug("Added memory mapping (%d): %llx %llx\n", entry,
216 imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
217 i++; entry++;
Peng Fan3c417282020-07-09 15:26:06 +0800218 }
Peng Fan59efa6b2019-08-27 06:25:27 +0000219
220 icache_enable();
221 dcache_enable();
222}
223
Peng Fan3c417282020-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;
Ye Li1c9bc0f2022-04-07 15:55:56 +0800230
231#ifdef PHYS_SDRAM_2_SIZE
232 *size += PHYS_SDRAM_2_SIZE;
233#endif
Peng Fan3c417282020-07-09 15:26:06 +0800234 return 0;
235}
236
237int dram_init(void)
238{
239 phys_size_t sdram_size;
240 int ret;
241
242 ret = board_phys_sdram_size(&sdram_size);
243 if (ret)
244 return ret;
245
246 /* rom_pointer[1] contains the size of TEE occupies */
Marek Vasut45dd3772022-12-22 01:46:38 +0100247 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[1])
Peng Fan3c417282020-07-09 15:26:06 +0800248 gd->ram_size = sdram_size - rom_pointer[1];
249 else
250 gd->ram_size = sdram_size;
251
Peng Fan3c417282020-07-09 15:26:06 +0800252 return 0;
253}
254
255int dram_init_banksize(void)
256{
257 int bank = 0;
258 int ret;
259 phys_size_t sdram_size;
Ye Li1c9bc0f2022-04-07 15:55:56 +0800260 phys_size_t sdram_b1_size, sdram_b2_size;
Peng Fan3c417282020-07-09 15:26:06 +0800261
262 ret = board_phys_sdram_size(&sdram_size);
263 if (ret)
264 return ret;
265
Ye Li1c9bc0f2022-04-07 15:55:56 +0800266 /* Bank 1 can't cross over 4GB space */
267 if (sdram_size > 0xc0000000) {
268 sdram_b1_size = 0xc0000000;
269 sdram_b2_size = sdram_size - 0xc0000000;
270 } else {
271 sdram_b1_size = sdram_size;
272 sdram_b2_size = 0;
273 }
274
Peng Fan3c417282020-07-09 15:26:06 +0800275 gd->bd->bi_dram[bank].start = PHYS_SDRAM;
Marek Vasut45dd3772022-12-22 01:46:38 +0100276 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[1]) {
Peng Fan3c417282020-07-09 15:26:06 +0800277 phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
278 phys_size_t optee_size = (size_t)rom_pointer[1];
279
280 gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
Ye Li1c9bc0f2022-04-07 15:55:56 +0800281 if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_b1_size)) {
Peng Fan3c417282020-07-09 15:26:06 +0800282 if (++bank >= CONFIG_NR_DRAM_BANKS) {
283 puts("CONFIG_NR_DRAM_BANKS is not enough\n");
284 return -1;
285 }
286
287 gd->bd->bi_dram[bank].start = optee_start + optee_size;
288 gd->bd->bi_dram[bank].size = PHYS_SDRAM +
Ye Li1c9bc0f2022-04-07 15:55:56 +0800289 sdram_b1_size - gd->bd->bi_dram[bank].start;
Peng Fan3c417282020-07-09 15:26:06 +0800290 }
291 } else {
Ye Li1c9bc0f2022-04-07 15:55:56 +0800292 gd->bd->bi_dram[bank].size = sdram_b1_size;
Peng Fan3c417282020-07-09 15:26:06 +0800293 }
294
Ye Li1c9bc0f2022-04-07 15:55:56 +0800295 if (sdram_b2_size) {
296 if (++bank >= CONFIG_NR_DRAM_BANKS) {
297 puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
298 return -1;
299 }
300 gd->bd->bi_dram[bank].start = 0x100000000UL;
301 gd->bd->bi_dram[bank].size = sdram_b2_size;
Peng Fan3c417282020-07-09 15:26:06 +0800302 }
Peng Fan3c417282020-07-09 15:26:06 +0800303
304 return 0;
305}
306
307phys_size_t get_effective_memsize(void)
308{
Ye Li1c9bc0f2022-04-07 15:55:56 +0800309 int ret;
310 phys_size_t sdram_size;
311 phys_size_t sdram_b1_size;
312 ret = board_phys_sdram_size(&sdram_size);
313 if (!ret) {
314 /* Bank 1 can't cross over 4GB space */
315 if (sdram_size > 0xc0000000) {
316 sdram_b1_size = 0xc0000000;
317 } else {
318 sdram_b1_size = sdram_size;
319 }
Peng Fan3c417282020-07-09 15:26:06 +0800320
Marek Vasut45dd3772022-12-22 01:46:38 +0100321 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[1]) {
Ye Li1c9bc0f2022-04-07 15:55:56 +0800322 /* We will relocate u-boot to Top of dram1. Tee position has two cases:
323 * 1. At the top of dram1, Then return the size removed optee size.
324 * 2. In the middle of dram1, return the size of dram1.
325 */
326 if ((rom_pointer[0] + rom_pointer[1]) == (PHYS_SDRAM + sdram_b1_size))
327 return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
328 }
329
330 return sdram_b1_size;
331 } else {
332 return PHYS_SDRAM_SIZE;
333 }
Peng Fan3c417282020-07-09 15:26:06 +0800334}
335
Pali Rohár049704f2022-09-09 17:32:40 +0200336phys_size_t board_get_usable_ram_top(phys_size_t total_size)
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200337{
Marek Vasut74f88b72022-04-14 15:51:46 +0200338 ulong top_addr;
Ying-Chun Liu (PaulLiu)5a6af8c2021-08-23 10:43:06 +0800339
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200340 /*
341 * Some IPs have their accessible address space restricted by
342 * the interconnect. Let's make sure U-Boot only ever uses the
343 * space below the 4G address boundary (which is 3GiB big),
344 * even when the effective available memory is bigger.
345 */
Marek Vasut74f88b72022-04-14 15:51:46 +0200346 top_addr = clamp_val((u64)PHYS_SDRAM + gd->ram_size, 0, 0xffffffff);
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200347
Ying-Chun Liu (PaulLiu)5a6af8c2021-08-23 10:43:06 +0800348 /*
349 * rom_pointer[0] stores the TEE memory start address.
350 * rom_pointer[1] stores the size TEE uses.
351 * We need to reserve the memory region for TEE.
352 */
Marek Vasut45dd3772022-12-22 01:46:38 +0100353 if (!IS_ENABLED(CONFIG_ARMV8_PSCI) && rom_pointer[0] &&
354 rom_pointer[1] && top_addr > rom_pointer[0])
Ying-Chun Liu (PaulLiu)5a6af8c2021-08-23 10:43:06 +0800355 top_addr = rom_pointer[0];
356
357 return top_addr;
Frieder Schrempfe27bddf2021-06-07 14:36:44 +0200358}
359
Peng Fan78db9a52019-08-27 06:25:17 +0000360static u32 get_cpu_variant_type(u32 type)
361{
362 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
363 struct fuse_bank *bank = &ocotp->bank[1];
364 struct fuse_bank1_regs *fuse =
365 (struct fuse_bank1_regs *)bank->fuse_regs;
366
367 u32 value = readl(&fuse->tester4);
368
Peng Fancb1a1de2020-02-05 17:34:54 +0800369 if (type == MXC_CPU_IMX8MQ) {
370 if ((value & 0x3) == 0x2)
371 return MXC_CPU_IMX8MD;
372 else if (value & 0x200000)
373 return MXC_CPU_IMX8MQL;
374
375 } else if (type == MXC_CPU_IMX8MM) {
Peng Fan78db9a52019-08-27 06:25:17 +0000376 switch (value & 0x3) {
377 case 2:
378 if (value & 0x1c0000)
379 return MXC_CPU_IMX8MMDL;
380 else
381 return MXC_CPU_IMX8MMD;
382 case 3:
383 if (value & 0x1c0000)
384 return MXC_CPU_IMX8MMSL;
385 else
386 return MXC_CPU_IMX8MMS;
387 default:
388 if (value & 0x1c0000)
389 return MXC_CPU_IMX8MML;
390 break;
391 }
Peng Fanc9154032020-02-05 17:39:27 +0800392 } else if (type == MXC_CPU_IMX8MN) {
393 switch (value & 0x3) {
394 case 2:
Ye Lic4f78cb2021-03-19 15:57:11 +0800395 if (value & 0x1000000) {
396 if (value & 0x10000000) /* MIPI DSI */
397 return MXC_CPU_IMX8MNUD;
398 else
399 return MXC_CPU_IMX8MNDL;
400 } else {
Peng Fanc9154032020-02-05 17:39:27 +0800401 return MXC_CPU_IMX8MND;
Ye Lic4f78cb2021-03-19 15:57:11 +0800402 }
Peng Fanc9154032020-02-05 17:39:27 +0800403 case 3:
Ye Lic4f78cb2021-03-19 15:57:11 +0800404 if (value & 0x1000000) {
405 if (value & 0x10000000) /* MIPI DSI */
406 return MXC_CPU_IMX8MNUS;
407 else
408 return MXC_CPU_IMX8MNSL;
409 } else {
Peng Fanc9154032020-02-05 17:39:27 +0800410 return MXC_CPU_IMX8MNS;
Ye Lic4f78cb2021-03-19 15:57:11 +0800411 }
Peng Fanc9154032020-02-05 17:39:27 +0800412 default:
Ye Lic4f78cb2021-03-19 15:57:11 +0800413 if (value & 0x1000000) {
414 if (value & 0x10000000) /* MIPI DSI */
415 return MXC_CPU_IMX8MNUQ;
416 else
417 return MXC_CPU_IMX8MNL;
418 }
Peng Fanc9154032020-02-05 17:39:27 +0800419 break;
420 }
Ye Lid1eee7e2020-04-20 20:12:54 -0700421 } else if (type == MXC_CPU_IMX8MP) {
422 u32 value0 = readl(&fuse->tester3);
423 u32 flag = 0;
424
425 if ((value0 & 0xc0000) == 0x80000)
426 return MXC_CPU_IMX8MPD;
427
428 /* vpu disabled */
429 if ((value0 & 0x43000000) == 0x43000000)
430 flag = 1;
431
432 /* npu disabled*/
433 if ((value & 0x8) == 0x8)
Peng Fan36bfd712022-04-07 15:55:52 +0800434 flag |= BIT(1);
Ye Lid1eee7e2020-04-20 20:12:54 -0700435
436 /* isp disabled */
437 if ((value & 0x3) == 0x3)
Peng Fan36bfd712022-04-07 15:55:52 +0800438 flag |= BIT(2);
439
440 /* gpu disabled */
441 if ((value & 0xc0) == 0xc0)
442 flag |= BIT(3);
443
444 /* lvds disabled */
445 if ((value & 0x180000) == 0x180000)
446 flag |= BIT(4);
447
448 /* mipi dsi disabled */
449 if ((value & 0x60000) == 0x60000)
450 flag |= BIT(5);
Ye Lid1eee7e2020-04-20 20:12:54 -0700451
452 switch (flag) {
Peng Fan36bfd712022-04-07 15:55:52 +0800453 case 0x3f:
454 return MXC_CPU_IMX8MPUL;
Ye Lid1eee7e2020-04-20 20:12:54 -0700455 case 7:
456 return MXC_CPU_IMX8MPL;
Ye Lid1eee7e2020-04-20 20:12:54 -0700457 case 2:
458 return MXC_CPU_IMX8MP6;
Ye Lid1eee7e2020-04-20 20:12:54 -0700459 default:
460 break;
461 }
462
Peng Fan78db9a52019-08-27 06:25:17 +0000463 }
464
465 return type;
466}
467
Peng Fanfcdbde72018-01-10 13:20:37 +0800468u32 get_cpu_rev(void)
469{
470 struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
471 u32 reg = readl(&ana_pll->digprog);
472 u32 type = (reg >> 16) & 0xff;
Peng Fan78db9a52019-08-27 06:25:17 +0000473 u32 major_low = (reg >> 8) & 0xff;
Peng Fanfcdbde72018-01-10 13:20:37 +0800474 u32 rom_version;
475
476 reg &= 0xff;
477
Peng Fan625b03d2019-12-27 10:14:02 +0800478 /* iMX8MP */
479 if (major_low == 0x43) {
Ye Lid1eee7e2020-04-20 20:12:54 -0700480 type = get_cpu_variant_type(MXC_CPU_IMX8MP);
Peng Fan625b03d2019-12-27 10:14:02 +0800481 } else if (major_low == 0x42) {
482 /* iMX8MN */
Peng Fanc9154032020-02-05 17:39:27 +0800483 type = get_cpu_variant_type(MXC_CPU_IMX8MN);
Peng Fan24341312019-06-27 17:23:49 +0800484 } else if (major_low == 0x41) {
Peng Fan78db9a52019-08-27 06:25:17 +0000485 type = get_cpu_variant_type(MXC_CPU_IMX8MM);
486 } else {
487 if (reg == CHIP_REV_1_0) {
488 /*
Peng Fan9e094452019-10-16 10:24:17 +0000489 * For B0 chip, the DIGPROG is not updated,
490 * it is still TO1.0. we have to check ROM
491 * version or OCOTP_READ_FUSE_DATA.
492 * 0xff0055aa is magic number for B1.
Peng Fan78db9a52019-08-27 06:25:17 +0000493 */
Peng Fan9e094452019-10-16 10:24:17 +0000494 if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
Ye Liea2b26fb2021-03-19 15:57:16 +0800495 /*
496 * B2 uses same DIGPROG and OCOTP_READ_FUSE_DATA value with B1,
497 * so have to check ROM to distinguish them
498 */
499 rom_version = readl((void __iomem *)ROM_VERSION_B0);
500 rom_version &= 0xff;
501 if (rom_version == CHIP_REV_2_2)
502 reg = CHIP_REV_2_2;
503 else
504 reg = CHIP_REV_2_1;
Peng Fan9e094452019-10-16 10:24:17 +0000505 } else {
506 rom_version =
507 readl((void __iomem *)ROM_VERSION_A0);
508 if (rom_version != CHIP_REV_1_0) {
509 rom_version = readl((void __iomem *)ROM_VERSION_B0);
Patrick Wildt6a4b07e2019-11-19 09:42:06 +0100510 rom_version &= 0xff;
Peng Fan9e094452019-10-16 10:24:17 +0000511 if (rom_version == CHIP_REV_2_0)
512 reg = CHIP_REV_2_0;
513 }
Peng Fan78db9a52019-08-27 06:25:17 +0000514 }
Peng Fanfcdbde72018-01-10 13:20:37 +0800515 }
Peng Fancb1a1de2020-02-05 17:34:54 +0800516
517 type = get_cpu_variant_type(type);
Peng Fanfcdbde72018-01-10 13:20:37 +0800518 }
519
520 return (type << 12) | reg;
521}
522
523static void imx_set_wdog_powerdown(bool enable)
524{
525 struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
526 struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
527 struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
528
529 /* Write to the PDE (Power Down Enable) bit */
530 writew(enable, &wdog1->wmcr);
531 writew(enable, &wdog2->wmcr);
532 writew(enable, &wdog3->wmcr);
533}
534
Simon Glass7fe32b32022-03-04 08:43:05 -0700535static int imx8m_check_clock(void *ctx, struct event *event)
Peng Fane663c702019-08-27 06:25:58 +0000536{
537 struct udevice *dev;
538 int ret;
539
Peng Fancd7c8062019-10-16 03:01:51 +0000540 if (CONFIG_IS_ENABLED(CLK)) {
541 ret = uclass_get_device_by_name(UCLASS_CLK,
542 "clock-controller@30380000",
543 &dev);
544 if (ret < 0) {
545 printf("Failed to find clock node. Check device tree\n");
546 return ret;
547 }
Peng Fane663c702019-08-27 06:25:58 +0000548 }
549
550 return 0;
551}
Simon Glass7fe32b32022-03-04 08:43:05 -0700552EVENT_SPY(EVT_DM_POST_INIT, imx8m_check_clock);
Peng Fane663c702019-08-27 06:25:58 +0000553
Marek Vasutfdf6bbb2022-09-19 21:37:07 +0200554static void imx8m_setup_snvs(void)
555{
556 /* Enable SNVS clock */
557 clock_enable(CCGR_SNVS, 1);
558 /* Initialize glitch detect */
559 writel(SNVS_LPPGDR_INIT, SNVS_BASE_ADDR + SNVS_LPLVDR);
560 /* Clear interrupt status */
561 writel(0xffffffff, SNVS_BASE_ADDR + SNVS_LPSR);
562}
563
Marek Vasut58552ab2022-12-22 01:46:42 +0100564static void imx8m_setup_csu_tzasc(void)
565{
566 const uintptr_t tzasc_base[4] = {
567 0x301f0000, 0x301f0000, 0x301f0000, 0x301f0000
568 };
569 int i, j;
570
571 if (!IS_ENABLED(CONFIG_ARMV8_PSCI))
572 return;
573
574 /* CSU */
575 for (i = 0; i < 64; i++)
576 writel(0x00ff00ff, (void *)CSU_BASE_ADDR + (4 * i));
577
578 /* TZASC */
579 for (j = 0; j < 4; j++) {
580 writel(0x77777777, (void *)(tzasc_base[j]));
581 writel(0x77777777, (void *)(tzasc_base[j]) + 0x4);
582 for (i = 0; i <= 0x10; i += 4)
583 writel(0, (void *)(tzasc_base[j]) + 0x40 + i);
584 }
585}
586
Peng Fanfcdbde72018-01-10 13:20:37 +0800587int arch_cpu_init(void)
588{
Peng Fan702339b2019-04-17 09:41:16 +0000589 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
Marek Vasut2fa763b2022-04-13 00:41:52 +0200590
591#if !CONFIG_IS_ENABLED(SYS_ICACHE_OFF)
592 icache_enable();
593#endif
594
Peng Fanfcdbde72018-01-10 13:20:37 +0800595 /*
Peng Fan0528ba02019-08-27 06:25:37 +0000596 * ROM might disable clock for SCTR,
597 * enable the clock before timer_init.
598 */
599 if (IS_ENABLED(CONFIG_SPL_BUILD))
600 clock_enable(CCGR_SCTR, 1);
601 /*
Peng Fanfcdbde72018-01-10 13:20:37 +0800602 * Init timer at very early state, because sscg pll setting
603 * will use it
604 */
605 timer_init();
606
607 if (IS_ENABLED(CONFIG_SPL_BUILD)) {
608 clock_init();
609 imx_set_wdog_powerdown(false);
Peng Fan7a42bf02020-07-09 13:52:41 +0800610
611 if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
612 is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
Ye Lic4f78cb2021-03-19 15:57:11 +0800613 is_imx8mnsl() || is_imx8mpd() || is_imx8mnud() || is_imx8mnus()) {
Peng Fan7a42bf02020-07-09 13:52:41 +0800614 /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
615 struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
616 struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
617 struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
618 struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
619
620 writel(0x1, &pgc_core2->pgcr);
621 writel(0x1, &pgc_core3->pgcr);
Ye Lic4f78cb2021-03-19 15:57:11 +0800622 if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl() || is_imx8mnus()) {
Peng Fan7a42bf02020-07-09 13:52:41 +0800623 writel(0x1, &pgc_core1->pgcr);
624 writel(0xE, &gpc->cpu_pgc_dn_trg);
625 } else {
626 writel(0xC, &gpc->cpu_pgc_dn_trg);
627 }
628 }
Peng Fanfcdbde72018-01-10 13:20:37 +0800629 }
630
Peng Fan702339b2019-04-17 09:41:16 +0000631 if (is_imx8mq()) {
632 clock_enable(CCGR_OCOTP, 1);
633 if (readl(&ocotp->ctrl) & 0x200)
634 writel(0x200, &ocotp->ctrl_clr);
635 }
636
Marek Vasutfdf6bbb2022-09-19 21:37:07 +0200637 imx8m_setup_snvs();
638
Marek Vasut58552ab2022-12-22 01:46:42 +0100639 imx8m_setup_csu_tzasc();
640
Peng Fanfcdbde72018-01-10 13:20:37 +0800641 return 0;
642}
643
Peng Fanb1821372019-09-16 03:09:36 +0000644#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
645struct rom_api *g_rom_api = (struct rom_api *)0x980;
Peng Fanb1821372019-09-16 03:09:36 +0000646#endif
647
Marek Vasuta5ee05c2021-07-03 04:55:33 +0200648#if defined(CONFIG_IMX8M)
649#include <spl.h>
650int spl_mmc_emmc_boot_partition(struct mmc *mmc)
651{
652 u32 *rom_log_addr = (u32 *)0x9e0;
653 u32 *rom_log;
654 u8 event_id;
655 int i, part;
656
657 part = default_spl_mmc_emmc_boot_partition(mmc);
658
659 /* If the ROM event log pointer is not valid. */
660 if (*rom_log_addr < 0x900000 || *rom_log_addr >= 0xb00000 ||
661 *rom_log_addr & 0x3)
662 return part;
663
664 /* Parse the ROM event ID version 2 log */
665 rom_log = (u32 *)(uintptr_t)(*rom_log_addr);
666 for (i = 0; i < 128; i++) {
667 event_id = rom_log[i] >> 24;
668 switch (event_id) {
669 case 0x00: /* End of list */
670 return part;
671 /* Log entries with 1 parameter, skip 1 */
672 case 0x80: /* Start to perform the device initialization */
673 case 0x81: /* The boot device initialization completes */
674 case 0x8f: /* The boot device initialization fails */
675 case 0x90: /* Start to read data from boot device */
676 case 0x91: /* Reading data from boot device completes */
677 case 0x9f: /* Reading data from boot device fails */
678 i += 1;
679 continue;
680 /* Log entries with 2 parameters, skip 2 */
681 case 0xa0: /* Image authentication result */
682 case 0xc0: /* Jump to the boot image soon */
683 i += 2;
684 continue;
685 /* Boot from the secondary boot image */
686 case 0x51:
687 /*
688 * Swap the eMMC boot partitions in case there was a
689 * fallback event (i.e. primary image was corrupted
690 * and that corruption was recognized by the BootROM),
691 * so the SPL loads the rest of the U-Boot from the
692 * correct eMMC boot partition, since the BootROM
693 * leaves the boot partition set to the corrupted one.
694 */
695 if (part == 1)
696 part = 2;
697 else if (part == 2)
698 part = 1;
699 continue;
700 default:
701 continue;
702 }
703 }
704
705 return part;
706}
707#endif
708
Peng Fanfcdbde72018-01-10 13:20:37 +0800709bool is_usb_boot(void)
710{
711 return get_boot_device() == USB_BOOT;
712}
713
714#ifdef CONFIG_OF_SYSTEM_SETUP
Peng Fan6036dba2020-07-09 14:06:49 +0800715bool check_fdt_new_path(void *blob)
716{
717 const char *soc_path = "/soc@0";
718 int nodeoff;
719
720 nodeoff = fdt_path_offset(blob, soc_path);
721 if (nodeoff < 0)
722 return false;
723
724 return true;
725}
726
727static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
Peng Fanfcdbde72018-01-10 13:20:37 +0800728{
729 int i = 0;
730 int rc;
731 int nodeoff;
Peng Fan6036dba2020-07-09 14:06:49 +0800732 const char *status = "disabled";
733
734 for (i = 0; i < size_array; i++) {
735 nodeoff = fdt_path_offset(blob, nodes_path[i]);
736 if (nodeoff < 0)
737 continue; /* Not found, skip it */
738
739 printf("Found %s node\n", nodes_path[i]);
740
741add_status:
742 rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
743 if (rc) {
744 if (rc == -FDT_ERR_NOSPACE) {
745 rc = fdt_increase_size(blob, 512);
746 if (!rc)
747 goto add_status;
748 }
749 printf("Unable to update property %s:%s, err=%s\n",
750 nodes_path[i], "status", fdt_strerror(rc));
751 } else {
752 printf("Modify %s:%s disabled\n",
753 nodes_path[i], "status");
754 }
755 }
756
757 return 0;
758}
759
760#ifdef CONFIG_IMX8MQ
761bool check_dcss_fused(void)
762{
763 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
764 struct fuse_bank *bank = &ocotp->bank[1];
765 struct fuse_bank1_regs *fuse =
766 (struct fuse_bank1_regs *)bank->fuse_regs;
767 u32 value = readl(&fuse->tester4);
768
769 if (value & 0x4000000)
770 return true;
771
772 return false;
773}
774
775static int disable_mipi_dsi_nodes(void *blob)
776{
777 static const char * const nodes_path[] = {
778 "/mipi_dsi@30A00000",
779 "/mipi_dsi_bridge@30A00000",
780 "/dsi_phy@30A00300",
781 "/soc@0/bus@30800000/mipi_dsi@30a00000",
Peng Fanc0e2f762021-03-19 15:57:13 +0800782 "/soc@0/bus@30800000/dphy@30a00300",
783 "/soc@0/bus@30800000/mipi-dsi@30a00000",
Peng Fan6036dba2020-07-09 14:06:49 +0800784 };
785
786 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
787}
788
789static int disable_dcss_nodes(void *blob)
790{
791 static const char * const nodes_path[] = {
792 "/dcss@0x32e00000",
793 "/dcss@32e00000",
794 "/hdmi@32c00000",
795 "/hdmi_cec@32c33800",
796 "/hdmi_drm@32c00000",
797 "/display-subsystem",
798 "/sound-hdmi",
799 "/sound-hdmi-arc",
800 "/soc@0/bus@32c00000/display-controller@32e00000",
801 "/soc@0/bus@32c00000/hdmi@32c00000",
802 };
803
804 return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
805}
806
807static int check_mipi_dsi_nodes(void *blob)
808{
809 static const char * const lcdif_path[] = {
810 "/lcdif@30320000",
Peng Fanc0e2f762021-03-19 15:57:13 +0800811 "/soc@0/bus@30000000/lcdif@30320000",
812 "/soc@0/bus@30000000/lcd-controller@30320000"
Peng Fan6036dba2020-07-09 14:06:49 +0800813 };
814 static const char * const mipi_dsi_path[] = {
815 "/mipi_dsi@30A00000",
816 "/soc@0/bus@30800000/mipi_dsi@30a00000"
817 };
818 static const char * const lcdif_ep_path[] = {
819 "/lcdif@30320000/port@0/mipi-dsi-endpoint",
Peng Fanc0e2f762021-03-19 15:57:13 +0800820 "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint",
821 "/soc@0/bus@30000000/lcd-controller@30320000/port@0/endpoint"
Peng Fan6036dba2020-07-09 14:06:49 +0800822 };
823 static const char * const mipi_dsi_ep_path[] = {
824 "/mipi_dsi@30A00000/port@1/endpoint",
Peng Fanc0e2f762021-03-19 15:57:13 +0800825 "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint",
826 "/soc@0/bus@30800000/mipi-dsi@30a00000/ports/port@0/endpoint@0"
Peng Fan6036dba2020-07-09 14:06:49 +0800827 };
828
829 int lookup_node;
830 int nodeoff;
831 bool new_path = check_fdt_new_path(blob);
832 int i = new_path ? 1 : 0;
833
834 nodeoff = fdt_path_offset(blob, lcdif_path[i]);
835 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
836 /*
837 * If can't find lcdif node or lcdif node is disabled,
838 * then disable all mipi dsi, since they only can input
839 * from DCSS
840 */
841 return disable_mipi_dsi_nodes(blob);
842 }
843
844 nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
845 if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
846 return 0;
847
848 nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
849 if (nodeoff < 0) {
850 /*
851 * If can't find lcdif endpoint, then disable all mipi dsi,
852 * since they only can input from DCSS
853 */
854 return disable_mipi_dsi_nodes(blob);
855 }
856
857 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
858 nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
859
860 if (nodeoff > 0 && nodeoff == lookup_node)
861 return 0;
862
863 return disable_mipi_dsi_nodes(blob);
864}
865#endif
866
867int disable_vpu_nodes(void *blob)
868{
869 static const char * const nodes_path_8mq[] = {
870 "/vpu@38300000",
871 "/soc@0/vpu@38300000"
872 };
873
874 static const char * const nodes_path_8mm[] = {
875 "/vpu_g1@38300000",
876 "/vpu_g2@38310000",
877 "/vpu_h1@38320000"
878 };
879
880 static const char * const nodes_path_8mp[] = {
881 "/vpu_g1@38300000",
882 "/vpu_g2@38310000",
883 "/vpu_vc8000e@38320000"
884 };
885
886 if (is_imx8mq())
887 return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
888 else if (is_imx8mm())
889 return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
890 else if (is_imx8mp())
891 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
892 else
893 return -EPERM;
894}
895
Ye Li98bcdf12021-03-19 15:57:09 +0800896#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
897static int low_drive_gpu_freq(void *blob)
898{
899 static const char *nodes_path_8mn[] = {
900 "/gpu@38000000",
901 "/soc@0/gpu@38000000"
902 };
903
904 int nodeoff, cnt, i;
905 u32 assignedclks[7];
906
907 nodeoff = fdt_path_offset(blob, nodes_path_8mn[0]);
908 if (nodeoff < 0)
909 return nodeoff;
910
911 cnt = fdtdec_get_int_array_count(blob, nodeoff, "assigned-clock-rates", assignedclks, 7);
912 if (cnt < 0)
913 return cnt;
914
915 if (cnt != 7)
916 printf("Warning: %s, assigned-clock-rates count %d\n", nodes_path_8mn[0], cnt);
917
918 assignedclks[cnt - 1] = 200000000;
919 assignedclks[cnt - 2] = 200000000;
920
921 for (i = 0; i < cnt; i++) {
922 debug("<%u>, ", assignedclks[i]);
923 assignedclks[i] = cpu_to_fdt32(assignedclks[i]);
924 }
925 debug("\n");
926
927 return fdt_setprop(blob, nodeoff, "assigned-clock-rates", &assignedclks, sizeof(assignedclks));
928}
929#endif
930
Peng Fan35bb6072022-04-07 15:55:53 +0800931static bool check_remote_endpoint(void *blob, const char *ep1, const char *ep2)
932{
933 int lookup_node;
934 int nodeoff;
935
936 nodeoff = fdt_path_offset(blob, ep1);
937 if (nodeoff) {
938 lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
939 nodeoff = fdt_path_offset(blob, ep2);
940
941 if (nodeoff > 0 && nodeoff == lookup_node)
942 return true;
943 }
944
945 return false;
946}
947
948int disable_dsi_lcdif_nodes(void *blob)
949{
950 int ret;
951
952 static const char * const dsi_path_8mp[] = {
953 "/soc@0/bus@32c00000/mipi_dsi@32e60000"
954 };
955
956 static const char * const lcdif_path_8mp[] = {
957 "/soc@0/bus@32c00000/lcd-controller@32e80000"
958 };
959
960 static const char * const lcdif_ep_path_8mp[] = {
961 "/soc@0/bus@32c00000/lcd-controller@32e80000/port@0/endpoint"
962 };
963 static const char * const dsi_ep_path_8mp[] = {
964 "/soc@0/bus@32c00000/mipi_dsi@32e60000/port@0/endpoint"
965 };
966
967 ret = disable_fdt_nodes(blob, dsi_path_8mp, ARRAY_SIZE(dsi_path_8mp));
968 if (ret)
969 return ret;
970
971 if (check_remote_endpoint(blob, dsi_ep_path_8mp[0], lcdif_ep_path_8mp[0])) {
972 /* Disable lcdif node */
973 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
974 }
975
976 return 0;
977}
978
979int disable_lvds_lcdif_nodes(void *blob)
980{
981 int ret, i;
982
983 static const char * const ldb_path_8mp[] = {
984 "/soc@0/bus@32c00000/ldb@32ec005c",
985 "/soc@0/bus@32c00000/phy@32ec0128"
986 };
987
988 static const char * const lcdif_path_8mp[] = {
989 "/soc@0/bus@32c00000/lcd-controller@32e90000"
990 };
991
992 static const char * const lcdif_ep_path_8mp[] = {
993 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@0",
994 "/soc@0/bus@32c00000/lcd-controller@32e90000/port@0/endpoint@1"
995 };
996 static const char * const ldb_ep_path_8mp[] = {
997 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@0/port@0/endpoint",
998 "/soc@0/bus@32c00000/ldb@32ec005c/lvds-channel@1/port@0/endpoint"
999 };
1000
1001 ret = disable_fdt_nodes(blob, ldb_path_8mp, ARRAY_SIZE(ldb_path_8mp));
1002 if (ret)
1003 return ret;
1004
1005 for (i = 0; i < ARRAY_SIZE(ldb_ep_path_8mp); i++) {
1006 if (check_remote_endpoint(blob, ldb_ep_path_8mp[i], lcdif_ep_path_8mp[i])) {
1007 /* Disable lcdif node */
1008 return disable_fdt_nodes(blob, lcdif_path_8mp, ARRAY_SIZE(lcdif_path_8mp));
1009 }
1010 }
1011
1012 return 0;
1013}
1014
Peng Fan6036dba2020-07-09 14:06:49 +08001015int disable_gpu_nodes(void *blob)
1016{
1017 static const char * const nodes_path_8mn[] = {
Peng Fanc0e2f762021-03-19 15:57:13 +08001018 "/gpu@38000000",
1019 "/soc@/gpu@38000000"
Peng Fan6036dba2020-07-09 14:06:49 +08001020 };
1021
Peng Fan35bb6072022-04-07 15:55:53 +08001022 static const char * const nodes_path_8mp[] = {
1023 "/gpu3d@38000000",
1024 "/gpu2d@38008000"
1025 };
1026
1027 if (is_imx8mp())
1028 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1029 else
1030 return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
Peng Fan6036dba2020-07-09 14:06:49 +08001031}
1032
1033int disable_npu_nodes(void *blob)
1034{
1035 static const char * const nodes_path_8mp[] = {
1036 "/vipsi@38500000"
1037 };
1038
1039 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1040}
1041
1042int disable_isp_nodes(void *blob)
1043{
1044 static const char * const nodes_path_8mp[] = {
1045 "/soc@0/bus@32c00000/camera/isp@32e10000",
1046 "/soc@0/bus@32c00000/camera/isp@32e20000"
1047 };
1048
1049 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1050}
1051
1052int disable_dsp_nodes(void *blob)
1053{
1054 static const char * const nodes_path_8mp[] = {
1055 "/dsp@3b6e8000"
1056 };
1057
1058 return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
1059}
1060
Ye Li4e83c052021-03-19 15:57:12 +08001061static void disable_thermal_cpu_nodes(void *blob, u32 disabled_cores)
1062{
1063 static const char * const thermal_path[] = {
1064 "/thermal-zones/cpu-thermal/cooling-maps/map0"
1065 };
1066
1067 int nodeoff, cnt, i, ret, j;
1068 u32 cooling_dev[12];
1069
1070 for (i = 0; i < ARRAY_SIZE(thermal_path); i++) {
1071 nodeoff = fdt_path_offset(blob, thermal_path[i]);
1072 if (nodeoff < 0)
1073 continue; /* Not found, skip it */
1074
1075 cnt = fdtdec_get_int_array_count(blob, nodeoff, "cooling-device", cooling_dev, 12);
1076 if (cnt < 0)
1077 continue;
1078
1079 if (cnt != 12)
1080 printf("Warning: %s, cooling-device count %d\n", thermal_path[i], cnt);
1081
1082 for (j = 0; j < cnt; j++)
1083 cooling_dev[j] = cpu_to_fdt32(cooling_dev[j]);
1084
1085 ret = fdt_setprop(blob, nodeoff, "cooling-device", &cooling_dev,
1086 sizeof(u32) * (12 - disabled_cores * 3));
1087 if (ret < 0) {
1088 printf("Warning: %s, cooling-device setprop failed %d\n",
1089 thermal_path[i], ret);
1090 continue;
1091 }
1092
1093 printf("Update node %s, cooling-device prop\n", thermal_path[i]);
1094 }
1095}
1096
1097static void disable_pmu_cpu_nodes(void *blob, u32 disabled_cores)
1098{
1099 static const char * const pmu_path[] = {
1100 "/pmu"
1101 };
1102
1103 int nodeoff, cnt, i, ret, j;
1104 u32 irq_affinity[4];
1105
1106 for (i = 0; i < ARRAY_SIZE(pmu_path); i++) {
1107 nodeoff = fdt_path_offset(blob, pmu_path[i]);
1108 if (nodeoff < 0)
1109 continue; /* Not found, skip it */
1110
1111 cnt = fdtdec_get_int_array_count(blob, nodeoff, "interrupt-affinity",
1112 irq_affinity, 4);
1113 if (cnt < 0)
1114 continue;
1115
1116 if (cnt != 4)
1117 printf("Warning: %s, interrupt-affinity count %d\n", pmu_path[i], cnt);
1118
1119 for (j = 0; j < cnt; j++)
1120 irq_affinity[j] = cpu_to_fdt32(irq_affinity[j]);
1121
1122 ret = fdt_setprop(blob, nodeoff, "interrupt-affinity", &irq_affinity,
1123 sizeof(u32) * (4 - disabled_cores));
1124 if (ret < 0) {
1125 printf("Warning: %s, interrupt-affinity setprop failed %d\n",
1126 pmu_path[i], ret);
1127 continue;
1128 }
1129
1130 printf("Update node %s, interrupt-affinity prop\n", pmu_path[i]);
1131 }
1132}
1133
Peng Fan6036dba2020-07-09 14:06:49 +08001134static int disable_cpu_nodes(void *blob, u32 disabled_cores)
1135{
1136 static const char * const nodes_path[] = {
1137 "/cpus/cpu@1",
1138 "/cpus/cpu@2",
1139 "/cpus/cpu@3",
1140 };
1141 u32 i = 0;
1142 int rc;
1143 int nodeoff;
1144
1145 if (disabled_cores > 3)
1146 return -EINVAL;
1147
1148 i = 3 - disabled_cores;
1149
1150 for (; i < 3; i++) {
1151 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1152 if (nodeoff < 0)
1153 continue; /* Not found, skip it */
1154
1155 debug("Found %s node\n", nodes_path[i]);
1156
1157 rc = fdt_del_node(blob, nodeoff);
1158 if (rc < 0) {
1159 printf("Unable to delete node %s, err=%s\n",
1160 nodes_path[i], fdt_strerror(rc));
1161 } else {
1162 printf("Delete node %s\n", nodes_path[i]);
1163 }
1164 }
1165
Ye Li4e83c052021-03-19 15:57:12 +08001166 disable_thermal_cpu_nodes(blob, disabled_cores);
1167 disable_pmu_cpu_nodes(blob, disabled_cores);
1168
Peng Fan6036dba2020-07-09 14:06:49 +08001169 return 0;
1170}
1171
Peng Fan8325ef32022-04-07 15:55:54 +08001172static int cleanup_nodes_for_efi(void *blob)
1173{
Peng Fan1166bd42022-04-07 15:55:55 +08001174 static const char * const path[][2] = {
1175 { "/soc@0/bus@32c00000/usb@32e40000", "extcon" },
1176 { "/soc@0/bus@32c00000/usb@32e50000", "extcon" },
1177 { "/soc@0/bus@30800000/ethernet@30be0000", "phy-reset-gpios" },
1178 { "/soc@0/bus@30800000/ethernet@30bf0000", "phy-reset-gpios" }
1179 };
Peng Fan8325ef32022-04-07 15:55:54 +08001180 int nodeoff, i, rc;
1181
Peng Fan1166bd42022-04-07 15:55:55 +08001182 for (i = 0; i < ARRAY_SIZE(path); i++) {
1183 nodeoff = fdt_path_offset(blob, path[i][0]);
Peng Fan8325ef32022-04-07 15:55:54 +08001184 if (nodeoff < 0)
1185 continue; /* Not found, skip it */
Peng Fan1166bd42022-04-07 15:55:55 +08001186 debug("Found %s node\n", path[i][0]);
Peng Fan8325ef32022-04-07 15:55:54 +08001187
Peng Fan1166bd42022-04-07 15:55:55 +08001188 rc = fdt_delprop(blob, nodeoff, path[i][1]);
Peng Fan8325ef32022-04-07 15:55:54 +08001189 if (rc == -FDT_ERR_NOTFOUND)
1190 continue;
1191 if (rc) {
1192 printf("Unable to update property %s:%s, err=%s\n",
Peng Fan1166bd42022-04-07 15:55:55 +08001193 path[i][0], path[i][1], fdt_strerror(rc));
Peng Fan8325ef32022-04-07 15:55:54 +08001194 return rc;
1195 }
1196
Peng Fan1166bd42022-04-07 15:55:55 +08001197 printf("Remove %s:%s\n", path[i][0], path[i][1]);
Peng Fan8325ef32022-04-07 15:55:54 +08001198 }
1199
1200 return 0;
1201}
Peng Fan8325ef32022-04-07 15:55:54 +08001202
Andrejs Cainikovs0543a1e2022-05-27 15:20:42 +02001203static int fixup_thermal_trips(void *blob, const char *name)
1204{
1205 int minc, maxc;
1206 int node, trip;
1207
1208 node = fdt_path_offset(blob, "/thermal-zones");
1209 if (node < 0)
1210 return node;
1211
1212 node = fdt_subnode_offset(blob, node, name);
1213 if (node < 0)
1214 return node;
1215
1216 node = fdt_subnode_offset(blob, node, "trips");
1217 if (node < 0)
1218 return node;
1219
1220 get_cpu_temp_grade(&minc, &maxc);
1221
1222 fdt_for_each_subnode(trip, blob, node) {
1223 const char *type;
1224 int temp, ret;
1225
1226 type = fdt_getprop(blob, trip, "type", NULL);
1227 if (!type)
1228 continue;
1229
1230 temp = 0;
1231 if (!strcmp(type, "critical"))
1232 temp = 1000 * maxc;
1233 else if (!strcmp(type, "passive"))
1234 temp = 1000 * (maxc - 10);
1235 if (temp) {
1236 ret = fdt_setprop_u32(blob, trip, "temperature", temp);
1237 if (ret)
1238 return ret;
1239 }
1240 }
1241
1242 return 0;
1243}
1244
Masahiro Yamadab75d8dc2020-06-26 15:13:33 +09001245int ft_system_setup(void *blob, struct bd_info *bd)
Peng Fan6036dba2020-07-09 14:06:49 +08001246{
1247#ifdef CONFIG_IMX8MQ
1248 int i = 0;
1249 int rc;
1250 int nodeoff;
1251
1252 if (get_boot_device() == USB_BOOT) {
1253 disable_dcss_nodes(blob);
1254
1255 bool new_path = check_fdt_new_path(blob);
1256 int v = new_path ? 1 : 0;
1257 static const char * const usb_dwc3_path[] = {
1258 "/usb@38100000/dwc3",
1259 "/soc@0/usb@38100000"
1260 };
1261
1262 nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
1263 if (nodeoff >= 0) {
1264 const char *speed = "high-speed";
1265
1266 printf("Found %s node\n", usb_dwc3_path[v]);
1267
1268usb_modify_speed:
1269
1270 rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
1271 if (rc) {
1272 if (rc == -FDT_ERR_NOSPACE) {
1273 rc = fdt_increase_size(blob, 512);
1274 if (!rc)
1275 goto usb_modify_speed;
1276 }
1277 printf("Unable to set property %s:%s, err=%s\n",
1278 usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
1279 } else {
1280 printf("Modify %s:%s = %s\n",
1281 usb_dwc3_path[v], "maximum-speed", speed);
1282 }
1283 } else {
1284 printf("Can't found %s node\n", usb_dwc3_path[v]);
1285 }
1286 }
Peng Fanfcdbde72018-01-10 13:20:37 +08001287
1288 /* Disable the CPU idle for A0 chip since the HW does not support it */
1289 if (is_soc_rev(CHIP_REV_1_0)) {
1290 static const char * const nodes_path[] = {
1291 "/cpus/cpu@0",
1292 "/cpus/cpu@1",
1293 "/cpus/cpu@2",
1294 "/cpus/cpu@3",
1295 };
1296
1297 for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
1298 nodeoff = fdt_path_offset(blob, nodes_path[i]);
1299 if (nodeoff < 0)
1300 continue; /* Not found, skip it */
1301
Marek Vasutdabaabd2020-04-24 21:37:33 +02001302 debug("Found %s node\n", nodes_path[i]);
Peng Fanfcdbde72018-01-10 13:20:37 +08001303
1304 rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
Marek Vasutdabaabd2020-04-24 21:37:33 +02001305 if (rc == -FDT_ERR_NOTFOUND)
1306 continue;
Peng Fanfcdbde72018-01-10 13:20:37 +08001307 if (rc) {
1308 printf("Unable to update property %s:%s, err=%s\n",
1309 nodes_path[i], "status", fdt_strerror(rc));
1310 return rc;
1311 }
1312
Marek Vasutdabaabd2020-04-24 21:37:33 +02001313 debug("Remove %s:%s\n", nodes_path[i],
Peng Fanfcdbde72018-01-10 13:20:37 +08001314 "cpu-idle-states");
1315 }
1316 }
1317
Peng Fan6036dba2020-07-09 14:06:49 +08001318 if (is_imx8mql()) {
1319 disable_vpu_nodes(blob);
1320 if (check_dcss_fused()) {
1321 printf("DCSS is fused\n");
1322 disable_dcss_nodes(blob);
1323 check_mipi_dsi_nodes(blob);
1324 }
1325 }
1326
1327 if (is_imx8md())
1328 disable_cpu_nodes(blob, 2);
1329
1330#elif defined(CONFIG_IMX8MM)
1331 if (is_imx8mml() || is_imx8mmdl() || is_imx8mmsl())
1332 disable_vpu_nodes(blob);
1333
1334 if (is_imx8mmd() || is_imx8mmdl())
1335 disable_cpu_nodes(blob, 2);
1336 else if (is_imx8mms() || is_imx8mmsl())
1337 disable_cpu_nodes(blob, 3);
1338
1339#elif defined(CONFIG_IMX8MN)
1340 if (is_imx8mnl() || is_imx8mndl() || is_imx8mnsl())
1341 disable_gpu_nodes(blob);
Ye Li98bcdf12021-03-19 15:57:09 +08001342#ifdef CONFIG_IMX8MN_LOW_DRIVE_MODE
1343 else {
1344 int ldm_gpu = low_drive_gpu_freq(blob);
1345
1346 if (ldm_gpu < 0)
1347 printf("Update GPU node assigned-clock-rates failed\n");
1348 else
1349 printf("Update GPU node assigned-clock-rates ok\n");
1350 }
1351#endif
Peng Fan6036dba2020-07-09 14:06:49 +08001352
Ye Lic4f78cb2021-03-19 15:57:11 +08001353 if (is_imx8mnd() || is_imx8mndl() || is_imx8mnud())
Peng Fan6036dba2020-07-09 14:06:49 +08001354 disable_cpu_nodes(blob, 2);
Ye Lic4f78cb2021-03-19 15:57:11 +08001355 else if (is_imx8mns() || is_imx8mnsl() || is_imx8mnus())
Peng Fan6036dba2020-07-09 14:06:49 +08001356 disable_cpu_nodes(blob, 3);
1357
1358#elif defined(CONFIG_IMX8MP)
Peng Fan35bb6072022-04-07 15:55:53 +08001359 if (is_imx8mpul()) {
1360 /* Disable GPU */
1361 disable_gpu_nodes(blob);
1362
1363 /* Disable DSI */
1364 disable_dsi_lcdif_nodes(blob);
1365
1366 /* Disable LVDS */
1367 disable_lvds_lcdif_nodes(blob);
1368 }
1369
1370 if (is_imx8mpul() || is_imx8mpl())
Peng Fan6036dba2020-07-09 14:06:49 +08001371 disable_vpu_nodes(blob);
1372
Peng Fan35bb6072022-04-07 15:55:53 +08001373 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan6036dba2020-07-09 14:06:49 +08001374 disable_npu_nodes(blob);
1375
Peng Fan35bb6072022-04-07 15:55:53 +08001376 if (is_imx8mpul() || is_imx8mpl())
Peng Fan6036dba2020-07-09 14:06:49 +08001377 disable_isp_nodes(blob);
1378
Peng Fan35bb6072022-04-07 15:55:53 +08001379 if (is_imx8mpul() || is_imx8mpl() || is_imx8mp6())
Peng Fan6036dba2020-07-09 14:06:49 +08001380 disable_dsp_nodes(blob);
1381
1382 if (is_imx8mpd())
1383 disable_cpu_nodes(blob, 2);
1384#endif
1385
Peng Fan1166bd42022-04-07 15:55:55 +08001386 cleanup_nodes_for_efi(blob);
Andrejs Cainikovs0543a1e2022-05-27 15:20:42 +02001387
1388 if (fixup_thermal_trips(blob, "cpu-thermal"))
1389 printf("Failed to update cpu-thermal trip(s)");
1390 if (IS_ENABLED(CONFIG_IMX8MP) &&
1391 fixup_thermal_trips(blob, "soc-thermal"))
1392 printf("Failed to update soc-thermal trip(s)");
1393
Peng Fanfcdbde72018-01-10 13:20:37 +08001394 return 0;
1395}
1396#endif
1397
Peng Fan35bb6072022-04-07 15:55:53 +08001398#ifdef CONFIG_OF_BOARD_FIXUP
1399#ifndef CONFIG_SPL_BUILD
1400int board_fix_fdt(void *fdt)
1401{
1402 if (is_imx8mpul()) {
1403 int i = 0;
1404 int nodeoff, ret;
1405 const char *status = "disabled";
1406 static const char * const dsi_nodes[] = {
1407 "/soc@0/bus@32c00000/mipi_dsi@32e60000",
1408 "/soc@0/bus@32c00000/lcd-controller@32e80000",
1409 "/dsi-host"
1410 };
1411
1412 for (i = 0; i < ARRAY_SIZE(dsi_nodes); i++) {
1413 nodeoff = fdt_path_offset(fdt, dsi_nodes[i]);
1414 if (nodeoff > 0) {
1415set_status:
1416 ret = fdt_setprop(fdt, nodeoff, "status", status,
1417 strlen(status) + 1);
1418 if (ret == -FDT_ERR_NOSPACE) {
1419 ret = fdt_increase_size(fdt, 512);
1420 if (!ret)
1421 goto set_status;
1422 }
1423 }
1424 }
1425 }
1426
1427 return 0;
1428}
1429#endif
1430#endif
1431
Marek Vasutefa1a622020-04-29 15:04:21 +02001432#if !CONFIG_IS_ENABLED(SYSRESET)
Harald Seiler35b65dd2020-12-15 16:47:52 +01001433void reset_cpu(void)
Peng Fanfcdbde72018-01-10 13:20:37 +08001434{
Claudius Heinec5635a02020-04-29 15:04:23 +02001435 struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
Peng Fanfcdbde72018-01-10 13:20:37 +08001436
Ye Li72479742019-12-09 00:47:18 -08001437 /* Clear WDA to trigger WDOG_B immediately */
1438 writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
Peng Fand2041722019-08-27 06:25:41 +00001439
Ye Li72479742019-12-09 00:47:18 -08001440 while (1) {
1441 /*
Harald Seiler568af922020-04-29 15:04:22 +02001442 * spin for .5 seconds before reset
Ye Li72479742019-12-09 00:47:18 -08001443 */
1444 }
Peng Fanfcdbde72018-01-10 13:20:37 +08001445}
Peng Fand2041722019-08-27 06:25:41 +00001446#endif
Peng Fana07bcec2020-04-22 10:51:13 +08001447
1448#if defined(CONFIG_ARCH_MISC_INIT)
Peng Fana07bcec2020-04-22 10:51:13 +08001449int arch_misc_init(void)
1450{
Gaurav Jain2cddfcb2022-03-24 11:50:27 +05301451 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
1452 struct udevice *dev;
1453 int ret;
1454
1455 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
1456 if (ret)
Ye Licda8f872022-05-11 13:56:20 +05301457 printf("Failed to initialize caam_jr: %d\n", ret);
Gaurav Jain2cddfcb2022-03-24 11:50:27 +05301458 }
Peng Fana07bcec2020-04-22 10:51:13 +08001459
1460 return 0;
1461}
1462#endif
Ye Li70487ff2020-05-03 22:19:52 +08001463
1464void imx_tmu_arch_init(void *reg_base)
1465{
Ye Li94c693d2020-05-03 22:19:53 +08001466 if (is_imx8mm() || is_imx8mn()) {
Ye Li70487ff2020-05-03 22:19:52 +08001467 /* Load TCALIV and TASR from fuses */
1468 struct ocotp_regs *ocotp =
1469 (struct ocotp_regs *)OCOTP_BASE_ADDR;
1470 struct fuse_bank *bank = &ocotp->bank[3];
1471 struct fuse_bank3_regs *fuse =
1472 (struct fuse_bank3_regs *)bank->fuse_regs;
1473
1474 u32 tca_rt, tca_hr, tca_en;
1475 u32 buf_vref, buf_slope;
1476
1477 tca_rt = fuse->ana0 & 0xFF;
1478 tca_hr = (fuse->ana0 & 0xFF00) >> 8;
1479 tca_en = (fuse->ana0 & 0x2000000) >> 25;
1480
1481 buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
1482 buf_slope = (fuse->ana0 & 0xF0000) >> 16;
1483
1484 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1485 writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
1486 (ulong)reg_base + 0x30);
1487 }
Ye Liebb9aab2020-05-03 22:19:54 +08001488#ifdef CONFIG_IMX8MP
1489 /* Load TCALIV0/1/m40 and TRIM from fuses */
1490 struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
1491 struct fuse_bank *bank = &ocotp->bank[38];
1492 struct fuse_bank38_regs *fuse =
1493 (struct fuse_bank38_regs *)bank->fuse_regs;
1494 struct fuse_bank *bank2 = &ocotp->bank[39];
1495 struct fuse_bank39_regs *fuse2 =
1496 (struct fuse_bank39_regs *)bank2->fuse_regs;
1497 u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
1498 u32 reg;
1499 u32 tca40[2], tca25[2], tca105[2];
1500
1501 /* For blank sample */
1502 if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
1503 !fuse->ana_trim4 && !fuse2->ana_trim5) {
1504 /* Use a default 25C binary codes */
1505 tca25[0] = 1596;
Ye Li3462b552020-05-03 22:19:55 +08001506 tca25[1] = 1596;
Ye Liebb9aab2020-05-03 22:19:54 +08001507 writel(tca25[0], (ulong)reg_base + 0x30);
Ye Li3462b552020-05-03 22:19:55 +08001508 writel(tca25[1], (ulong)reg_base + 0x34);
Ye Liebb9aab2020-05-03 22:19:54 +08001509 return;
1510 }
1511
1512 buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
1513 buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
1514 bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
1515 bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
1516 vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
1517 writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1518
1519 reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
1520 writel(reg, (ulong)reg_base + 0x3c);
1521
1522 tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
1523 tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
1524 tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
1525 tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
1526 tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
1527 tca25[1] = fuse2->ana_trim5 & 0xFFF;
1528 tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
1529
1530 /* use 25c for 1p calibration */
1531 writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
1532 writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
1533 writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
1534#endif
Ye Li70487ff2020-05-03 22:19:52 +08001535}
Peng Fan2f3c9202020-07-09 13:39:26 +08001536
1537#if defined(CONFIG_SPL_BUILD)
1538#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1539bool serror_need_skip = true;
1540
Sean Andersone97ac472022-03-22 17:17:35 -04001541void do_error(struct pt_regs *pt_regs)
Peng Fan2f3c9202020-07-09 13:39:26 +08001542{
1543 /*
1544 * If stack is still in ROM reserved OCRAM not switch to SPL,
1545 * it is the ROM SError
1546 */
1547 ulong sp;
1548
1549 asm volatile("mov %0, sp" : "=r"(sp) : );
1550
1551 if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1552 /* Check for ERR050342, imx8mq HDCP enabled parts */
1553 if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1554 serror_need_skip = false;
1555 return; /* Do nothing skip the SError in ROM */
1556 }
1557
1558 /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1559 if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1560 serror_need_skip = false;
1561 return; /* Do nothing skip the SError in ROM */
1562 }
1563 }
1564
1565 efi_restore_gd();
Sean Andersone97ac472022-03-22 17:17:35 -04001566 printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
Peng Fan2f3c9202020-07-09 13:39:26 +08001567 show_regs(pt_regs);
1568 panic("Resetting CPU ...\n");
1569}
1570#endif
1571#endif
Ye Li2707faf2019-07-15 01:16:46 -07001572
1573#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
Marek Vasute4dc2d02022-04-06 02:21:34 +02001574enum env_location arch_env_get_location(enum env_operation op, int prio)
Ye Li2707faf2019-07-15 01:16:46 -07001575{
1576 enum boot_device dev = get_boot_device();
Ye Li2707faf2019-07-15 01:16:46 -07001577
1578 if (prio)
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001579 return ENVL_UNKNOWN;
Ye Li2707faf2019-07-15 01:16:46 -07001580
1581 switch (dev) {
Fabio Estevamd1759822022-04-21 15:05:23 -03001582 case USB_BOOT:
1583 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1584 return ENVL_SPI_FLASH;
1585 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1586 return ENVL_NAND;
1587 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1588 return ENVL_MMC;
1589 if (IS_ENABLED(CONFIG_ENV_IS_NOWHERE))
1590 return ENVL_NOWHERE;
1591 return ENVL_UNKNOWN;
Ye Li2707faf2019-07-15 01:16:46 -07001592 case QSPI_BOOT:
Marek Vasute26d0152022-03-25 18:59:28 +01001593 case SPI_NOR_BOOT:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001594 if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
1595 return ENVL_SPI_FLASH;
1596 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001597 case NAND_BOOT:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001598 if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
1599 return ENVL_NAND;
1600 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001601 case SD1_BOOT:
1602 case SD2_BOOT:
1603 case SD3_BOOT:
1604 case MMC1_BOOT:
1605 case MMC2_BOOT:
1606 case MMC3_BOOT:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001607 if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
1608 return ENVL_MMC;
1609 else if (IS_ENABLED(CONFIG_ENV_IS_IN_EXT4))
1610 return ENVL_EXT4;
1611 else if (IS_ENABLED(CONFIG_ENV_IS_IN_FAT))
1612 return ENVL_FAT;
1613 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001614 default:
Ricardo Salveti89ca5a72021-10-20 16:16:26 -03001615 return ENVL_NOWHERE;
Ye Li2707faf2019-07-15 01:16:46 -07001616 }
Ye Li2707faf2019-07-15 01:16:46 -07001617}
1618
Ye Li2707faf2019-07-15 01:16:46 -07001619#endif
Peng Fan5dd9db82022-04-29 16:03:14 +08001620
1621#ifdef CONFIG_IMX_BOOTAUX
1622const struct rproc_att hostmap[] = {
1623 /* aux core , host core, size */
1624 { 0x00000000, 0x007e0000, 0x00020000 },
1625 /* OCRAM_S */
1626 { 0x00180000, 0x00180000, 0x00008000 },
1627 /* OCRAM */
1628 { 0x00900000, 0x00900000, 0x00020000 },
1629 /* OCRAM */
1630 { 0x00920000, 0x00920000, 0x00020000 },
1631 /* QSPI Code - alias */
1632 { 0x08000000, 0x08000000, 0x08000000 },
1633 /* DDR (Code) - alias */
1634 { 0x10000000, 0x80000000, 0x0FFE0000 },
1635 /* TCML */
1636 { 0x1FFE0000, 0x007E0000, 0x00040000 },
1637 /* OCRAM_S */
1638 { 0x20180000, 0x00180000, 0x00008000 },
1639 /* OCRAM */
1640 { 0x20200000, 0x00900000, 0x00040000 },
1641 /* DDR (Data) */
1642 { 0x40000000, 0x40000000, 0x80000000 },
1643 { /* sentinel */ }
1644};
Marek Vasut3f7afdd2022-12-13 05:46:07 +01001645
1646const struct rproc_att *imx_bootaux_get_hostmap(void)
1647{
1648 return hostmap;
1649}
Peng Fan5dd9db82022-04-29 16:03:14 +08001650#endif