blob: 37a5473ac7cf49e71908c1276dd596917d3f14d1 [file] [log] [blame]
Peng Fan2e6be072018-10-18 14:28:18 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
Gaurav Jaindb4dd6a2022-03-24 11:50:33 +05303 * Copyright 2018, 2021 NXP
Peng Fan2e6be072018-10-18 14:28:18 +02004 */
5
Peng Fan2e6be072018-10-18 14:28:18 +02006#include <clk.h>
Anatolij Gustschin9b39be92018-10-18 14:28:24 +02007#include <cpu.h>
Simon Glass1d91ba72019-11-14 12:57:37 -07008#include <cpu_func.h>
Peng Fan2e6be072018-10-18 14:28:18 +02009#include <dm.h>
Simon Glassfc557362022-03-04 08:43:05 -070010#include <event.h>
Simon Glass8e16b1e2019-12-28 10:45:05 -070011#include <init.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glass274e0b02020-05-10 11:39:56 -060013#include <asm/cache.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Peng Fan2e6be072018-10-18 14:28:18 +020015#include <dm/device-internal.h>
16#include <dm/lists.h>
17#include <dm/uclass.h>
18#include <errno.h>
Peng Fan617fc292020-05-05 20:28:41 +080019#include <spl.h>
Peng Fan48f9c4e2019-04-26 01:44:27 +000020#include <thermal.h>
Peng Fan2e0644a2023-04-28 12:08:09 +080021#include <firmware/imx/sci/sci.h>
Peng Fan29c9dd32018-10-18 14:28:19 +020022#include <asm/arch/sys_proto.h>
Peng Fan2e6be072018-10-18 14:28:18 +020023#include <asm/arch-imx/cpu.h>
24#include <asm/armv8/cpu.h>
Peng Fan4f211a52018-10-18 14:28:21 +020025#include <asm/armv8/mmu.h>
Peng Fand2aaf0c2020-05-05 20:28:39 +080026#include <asm/setup.h>
Peng Fan29c9dd32018-10-18 14:28:19 +020027#include <asm/mach-imx/boot_mode.h>
Ye Lic07ac742023-06-15 18:09:20 +080028#include <power-domain.h>
29#include <elf.h>
Ye Lic3169bd2020-05-05 20:28:42 +080030#include <spl.h>
Peng Fan2e6be072018-10-18 14:28:18 +020031
32DECLARE_GLOBAL_DATA_PTR;
33
Peng Fan14b4cd22018-10-18 14:28:22 +020034#define BT_PASSOVER_TAG 0x504F
35struct pass_over_info_t *get_pass_over_info(void)
36{
37 struct pass_over_info_t *p =
38 (struct pass_over_info_t *)PASS_OVER_INFO_ADDR;
39
40 if (p->barker != BT_PASSOVER_TAG ||
41 p->len != sizeof(struct pass_over_info_t))
42 return NULL;
43
44 return p;
45}
46
Igor Opaniukab5ffef2024-01-31 13:49:26 +010047static char *get_reset_cause(void)
48{
49 sc_pm_reset_reason_t reason;
50
Peng Fanddeb21a2024-10-09 16:29:36 +080051 if (sc_pm_reset_reason(-1, &reason))
Igor Opaniukab5ffef2024-01-31 13:49:26 +010052 return "Unknown reset";
53
54 switch (reason) {
55 case SC_PM_RESET_REASON_POR:
56 return "POR";
57 case SC_PM_RESET_REASON_JTAG:
58 return "JTAG reset ";
59 case SC_PM_RESET_REASON_SW:
60 return "Software reset";
61 case SC_PM_RESET_REASON_WDOG:
62 return "Watchdog reset";
63 case SC_PM_RESET_REASON_LOCKUP:
64 return "SCU lockup reset";
65 case SC_PM_RESET_REASON_SNVS:
66 return "SNVS reset";
67 case SC_PM_RESET_REASON_TEMP:
68 return "Temp panic reset";
69 case SC_PM_RESET_REASON_MSI:
70 return "MSI reset";
71 case SC_PM_RESET_REASON_UECC:
72 return "ECC reset";
73 case SC_PM_RESET_REASON_SCFW_WDOG:
74 return "SCFW watchdog reset";
75 case SC_PM_RESET_REASON_ROM_WDOG:
76 return "SCU ROM watchdog reset";
77 case SC_PM_RESET_REASON_SECO:
78 return "SECO reset";
79 case SC_PM_RESET_REASON_SCFW_FAULT:
80 return "SCFW fault reset";
81 default:
82 return "Unknown reset";
83 }
84}
85
Fabio Estevam70b39d02024-03-26 09:19:49 -030086__weak void reset_cpu(void)
87{
88}
89
Peng Fan14b4cd22018-10-18 14:28:22 +020090int arch_cpu_init(void)
91{
Simon Glass85ed77d2024-09-29 19:49:46 -060092#if defined(CONFIG_XPL_BUILD) && defined(CONFIG_SPL_RECOVER_DATA_SECTION)
Peng Fan617fc292020-05-05 20:28:41 +080093 spl_save_restore_data();
94#endif
95
Simon Glass85ed77d2024-09-29 19:49:46 -060096#ifdef CONFIG_XPL_BUILD
Peng Fan0bcec7f2019-01-18 08:58:38 +000097 struct pass_over_info_t *pass_over;
Peng Fan14b4cd22018-10-18 14:28:22 +020098
Peng Fan0bcec7f2019-01-18 08:58:38 +000099 if (is_soc_rev(CHIP_REV_A)) {
100 pass_over = get_pass_over_info();
101 if (pass_over && pass_over->g_ap_mu == 0) {
102 /*
103 * When ap_mu is 0, means the U-Boot booted
104 * from first container
105 */
106 sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS);
107 }
Peng Fan14b4cd22018-10-18 14:28:22 +0200108 }
Peng Fan0bcec7f2019-01-18 08:58:38 +0000109#endif
Peng Fan14b4cd22018-10-18 14:28:22 +0200110
111 return 0;
112}
113
Simon Glassb8357c12023-08-21 21:16:56 -0600114static int imx8_init_mu(void)
Peng Fan14b4cd22018-10-18 14:28:22 +0200115{
116 struct udevice *devp;
117 int node, ret;
118
119 node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu");
Peng Fan14b4cd22018-10-18 14:28:22 +0200120
Ye Lif2ea6f02019-08-26 08:11:42 +0000121 ret = uclass_get_device_by_of_offset(UCLASS_MISC, node, &devp);
Peng Fan14b4cd22018-10-18 14:28:22 +0200122 if (ret) {
Ye Lif2ea6f02019-08-26 08:11:42 +0000123 printf("could not get scu %d\n", ret);
Peng Fan14b4cd22018-10-18 14:28:22 +0200124 return ret;
125 }
126
Peng Fanee380c52019-08-26 08:11:49 +0000127 if (is_imx8qm()) {
128 ret = sc_pm_set_resource_power_mode(-1, SC_R_SMMU,
129 SC_PM_PW_MODE_ON);
130 if (ret)
131 return ret;
132 }
133
Peng Fan14b4cd22018-10-18 14:28:22 +0200134 return 0;
135}
Simon Glassb8357c12023-08-21 21:16:56 -0600136EVENT_SPY_SIMPLE(EVT_DM_POST_INIT_F, imx8_init_mu);
Peng Fan14b4cd22018-10-18 14:28:22 +0200137
Gaurav Jaindb4dd6a2022-03-24 11:50:33 +0530138#if defined(CONFIG_ARCH_MISC_INIT)
139int arch_misc_init(void)
140{
141 if (IS_ENABLED(CONFIG_FSL_CAAM)) {
142 struct udevice *dev;
143 int ret;
144
145 ret = uclass_get_device_by_driver(UCLASS_MISC, DM_DRIVER_GET(caam_jr), &dev);
146 if (ret)
Ye Liec346892022-05-11 13:56:20 +0530147 printf("Failed to initialize caam_jr: %d\n", ret);
Gaurav Jaindb4dd6a2022-03-24 11:50:33 +0530148 }
149
150 return 0;
151}
152#endif
153
Ye Lic07ac742023-06-15 18:09:20 +0800154#ifdef CONFIG_IMX_BOOTAUX
155
156#ifdef CONFIG_IMX8QM
157int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
158{
159 sc_rsrc_t core_rsrc, mu_rsrc;
160 sc_faddr_t tcml_addr;
161 u32 tcml_size = SZ_128K;
162 ulong addr;
Peng Fanddeb21a2024-10-09 16:29:36 +0800163 int ret;
Ye Lic07ac742023-06-15 18:09:20 +0800164
165 switch (core_id) {
166 case 0:
167 core_rsrc = SC_R_M4_0_PID0;
168 tcml_addr = 0x34FE0000;
169 mu_rsrc = SC_R_M4_0_MU_1A;
170 break;
171 case 1:
172 core_rsrc = SC_R_M4_1_PID0;
173 tcml_addr = 0x38FE0000;
174 mu_rsrc = SC_R_M4_1_MU_1A;
175 break;
176 default:
177 printf("Not support this core boot up, ID:%u\n", core_id);
178 return -EINVAL;
179 }
180
181 addr = (sc_faddr_t)boot_private_data;
182
183 if (addr >= tcml_addr && addr <= tcml_addr + tcml_size) {
184 printf("Wrong image address 0x%lx, should not in TCML\n",
185 addr);
186 return -EINVAL;
187 }
188
189 printf("Power on M4 and MU\n");
190
Peng Fanddeb21a2024-10-09 16:29:36 +0800191 ret = sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON);
192 if (ret)
193 return ret;
Ye Lic07ac742023-06-15 18:09:20 +0800194
Peng Fanddeb21a2024-10-09 16:29:36 +0800195 ret = sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON);
196 if (ret)
Ye Lic07ac742023-06-15 18:09:20 +0800197 return -EIO;
198
199 printf("Copy M4 image from 0x%lx to TCML 0x%lx\n", addr, (ulong)tcml_addr);
200
201 if (addr != tcml_addr)
202 memcpy((void *)tcml_addr, (void *)addr, tcml_size);
203
204 printf("Start M4 %u\n", core_id);
Peng Fanddeb21a2024-10-09 16:29:36 +0800205 ret = sc_pm_cpu_start(-1, core_rsrc, true, tcml_addr);
206 if (ret)
Ye Lic07ac742023-06-15 18:09:20 +0800207 return -EIO;
208
209 printf("bootaux complete\n");
210 return 0;
211}
212#endif
213
214#ifdef CONFIG_IMX8QXP
215int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
216{
217 sc_rsrc_t core_rsrc, mu_rsrc = SC_R_NONE;
218 sc_faddr_t aux_core_ram;
219 u32 size;
220 ulong addr;
Peng Fanddeb21a2024-10-09 16:29:36 +0800221 int ret;
Ye Lic07ac742023-06-15 18:09:20 +0800222
223 switch (core_id) {
224 case 0:
225 core_rsrc = SC_R_M4_0_PID0;
226 aux_core_ram = 0x34FE0000;
227 mu_rsrc = SC_R_M4_0_MU_1A;
228 size = SZ_128K;
229 break;
230 case 1:
231 core_rsrc = SC_R_DSP;
232 aux_core_ram = 0x596f8000;
233 size = SZ_2K;
234 break;
235 default:
236 printf("Not support this core boot up, ID:%u\n", core_id);
237 return -EINVAL;
238 }
239
240 addr = (sc_faddr_t)boot_private_data;
241
242 if (addr >= aux_core_ram && addr <= aux_core_ram + size) {
243 printf("Wrong image address 0x%lx, should not in aux core ram\n",
244 addr);
245 return -EINVAL;
246 }
247
248 printf("Power on aux core %d\n", core_id);
249
Peng Fanddeb21a2024-10-09 16:29:36 +0800250 ret = sc_pm_set_resource_power_mode(-1, core_rsrc, SC_PM_PW_MODE_ON);
251 if (ret)
252 return ret;
Ye Lic07ac742023-06-15 18:09:20 +0800253
254 if (mu_rsrc != SC_R_NONE) {
Peng Fanddeb21a2024-10-09 16:29:36 +0800255 ret = sc_pm_set_resource_power_mode(-1, mu_rsrc, SC_PM_PW_MODE_ON);
256 if (ret)
Ye Lic07ac742023-06-15 18:09:20 +0800257 return -EIO;
258 }
259
260 if (core_id == 1) {
261 struct power_domain pd;
262
Peng Fanddeb21a2024-10-09 16:29:36 +0800263 ret = sc_pm_clock_enable(-1, core_rsrc, SC_PM_CLK_PER, true, false);
264 if (ret) {
Ye Lic07ac742023-06-15 18:09:20 +0800265 printf("Error enable clock\n");
Peng Fanddeb21a2024-10-09 16:29:36 +0800266 return ret;
Ye Lic07ac742023-06-15 18:09:20 +0800267 }
268
Max Krummenacherc209c8f2024-08-07 15:39:11 +0200269 if (!imx8_power_domain_lookup_name("audio_sai0", &pd)) {
Ye Lic07ac742023-06-15 18:09:20 +0800270 if (power_domain_on(&pd)) {
271 printf("Error power on SAI0\n");
272 return -EIO;
273 }
274 }
275
Max Krummenacherc209c8f2024-08-07 15:39:11 +0200276 if (!imx8_power_domain_lookup_name("audio_ocram", &pd)) {
Ye Lic07ac742023-06-15 18:09:20 +0800277 if (power_domain_on(&pd)) {
278 printf("Error power on HIFI RAM\n");
279 return -EIO;
280 }
281 }
282 }
283
284 printf("Copy image from 0x%lx to 0x%lx\n", addr, (ulong)aux_core_ram);
285 if (core_id == 0) {
286 /* M4 use bin file */
287 memcpy((void *)aux_core_ram, (void *)addr, size);
288 } else {
289 /* HIFI use elf file */
290 if (!valid_elf_image(addr))
291 return -1;
292 addr = load_elf_image_shdr(addr);
293 }
294
295 printf("Start %s\n", core_id == 0 ? "M4" : "HIFI");
296
Peng Fanddeb21a2024-10-09 16:29:36 +0800297 ret = sc_pm_cpu_start(-1, core_rsrc, true, aux_core_ram);
298 if (ret)
299 return ret;
Ye Lic07ac742023-06-15 18:09:20 +0800300
301 printf("bootaux complete\n");
302 return 0;
303}
304#endif
305
306int arch_auxiliary_core_check_up(u32 core_id)
307{
308 sc_rsrc_t core_rsrc;
309 sc_pm_power_mode_t power_mode;
310
311 switch (core_id) {
312 case 0:
313 core_rsrc = SC_R_M4_0_PID0;
314 break;
315#ifdef CONFIG_IMX8QM
316 case 1:
317 core_rsrc = SC_R_M4_1_PID0;
318 break;
319#endif
320 default:
321 printf("Not support this core, ID:%u\n", core_id);
322 return 0;
323 }
324
Peng Fanddeb21a2024-10-09 16:29:36 +0800325 if (sc_pm_get_resource_power_mode(-1, core_rsrc, &power_mode))
Ye Lic07ac742023-06-15 18:09:20 +0800326 return 0;
327
328 if (power_mode != SC_PM_PW_MODE_OFF)
329 return 1;
330
331 return 0;
332}
333#endif
334
Peng Fan29c9dd32018-10-18 14:28:19 +0200335int print_bootinfo(void)
336{
337 enum boot_device bt_dev = get_boot_device();
338
339 puts("Boot: ");
340 switch (bt_dev) {
341 case SD1_BOOT:
342 puts("SD0\n");
343 break;
344 case SD2_BOOT:
345 puts("SD1\n");
346 break;
347 case SD3_BOOT:
348 puts("SD2\n");
349 break;
350 case MMC1_BOOT:
351 puts("MMC0\n");
352 break;
353 case MMC2_BOOT:
354 puts("MMC1\n");
355 break;
356 case MMC3_BOOT:
357 puts("MMC2\n");
358 break;
359 case FLEXSPI_BOOT:
360 puts("FLEXSPI\n");
361 break;
362 case SATA_BOOT:
363 puts("SATA\n");
364 break;
365 case NAND_BOOT:
366 puts("NAND\n");
367 break;
368 case USB_BOOT:
369 puts("USB\n");
370 break;
371 default:
372 printf("Unknown device %u\n", bt_dev);
373 break;
374 }
375
Igor Opaniukab5ffef2024-01-31 13:49:26 +0100376 printf("Reset cause: %s\n", get_reset_cause());
377
Peng Fan29c9dd32018-10-18 14:28:19 +0200378 return 0;
379}
380
381enum boot_device get_boot_device(void)
382{
383 enum boot_device boot_dev = SD1_BOOT;
384
385 sc_rsrc_t dev_rsrc;
386
387 sc_misc_get_boot_dev(-1, &dev_rsrc);
388
389 switch (dev_rsrc) {
390 case SC_R_SDHC_0:
391 boot_dev = MMC1_BOOT;
392 break;
393 case SC_R_SDHC_1:
394 boot_dev = SD2_BOOT;
395 break;
396 case SC_R_SDHC_2:
397 boot_dev = SD3_BOOT;
398 break;
399 case SC_R_NAND:
400 boot_dev = NAND_BOOT;
401 break;
402 case SC_R_FSPI_0:
403 boot_dev = FLEXSPI_BOOT;
404 break;
405 case SC_R_SATA_0:
406 boot_dev = SATA_BOOT;
407 break;
408 case SC_R_USB_0:
409 case SC_R_USB_1:
410 case SC_R_USB_2:
411 boot_dev = USB_BOOT;
412 break;
413 default:
414 break;
415 }
416
417 return boot_dev;
418}
Peng Fan93b6cfd2018-10-18 14:28:20 +0200419
Tom Riniae21e7f2021-08-30 09:16:29 -0400420#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
Peng Fand2aaf0c2020-05-05 20:28:39 +0800421#define FUSE_UNIQUE_ID_WORD0 16
422#define FUSE_UNIQUE_ID_WORD1 17
423void get_board_serial(struct tag_serialnr *serialnr)
424{
Peng Fan25b7eb42023-06-15 18:08:58 +0800425 int err;
Peng Fand2aaf0c2020-05-05 20:28:39 +0800426 u32 val1 = 0, val2 = 0;
427 u32 word1, word2;
428
429 if (!serialnr)
430 return;
431
432 word1 = FUSE_UNIQUE_ID_WORD0;
433 word2 = FUSE_UNIQUE_ID_WORD1;
434
435 err = sc_misc_otp_fuse_read(-1, word1, &val1);
Peng Fan25b7eb42023-06-15 18:08:58 +0800436 if (err) {
Peng Fand2aaf0c2020-05-05 20:28:39 +0800437 printf("%s fuse %d read error: %d\n", __func__, word1, err);
438 return;
439 }
440
441 err = sc_misc_otp_fuse_read(-1, word2, &val2);
Peng Fan25b7eb42023-06-15 18:08:58 +0800442 if (err) {
Peng Fand2aaf0c2020-05-05 20:28:39 +0800443 printf("%s fuse %d read error: %d\n", __func__, word2, err);
444 return;
445 }
446 serialnr->low = val1;
447 serialnr->high = val2;
448}
Tom Riniae21e7f2021-08-30 09:16:29 -0400449#endif /*CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG*/
Peng Fand2aaf0c2020-05-05 20:28:39 +0800450
Peng Fan93b6cfd2018-10-18 14:28:20 +0200451#ifdef CONFIG_ENV_IS_IN_MMC
452__weak int board_mmc_get_env_dev(int devno)
453{
454 return CONFIG_SYS_MMC_ENV_DEV;
455}
456
457int mmc_get_env_dev(void)
458{
459 sc_rsrc_t dev_rsrc;
460 int devno;
461
462 sc_misc_get_boot_dev(-1, &dev_rsrc);
463
464 switch (dev_rsrc) {
465 case SC_R_SDHC_0:
466 devno = 0;
467 break;
468 case SC_R_SDHC_1:
469 devno = 1;
470 break;
471 case SC_R_SDHC_2:
472 devno = 2;
473 break;
474 default:
475 /* If not boot from sd/mmc, use default value */
476 return CONFIG_SYS_MMC_ENV_DEV;
477 }
478
479 return board_mmc_get_env_dev(devno);
480}
481#endif
Peng Fan4f211a52018-10-18 14:28:21 +0200482
483#define MEMSTART_ALIGNMENT SZ_2M /* Align the memory start with 2MB */
484
485static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start,
486 sc_faddr_t *addr_end)
487{
488 sc_faddr_t start, end;
489 int ret;
490 bool owned;
491
492 owned = sc_rm_is_memreg_owned(-1, mr);
493 if (owned) {
494 ret = sc_rm_get_memreg_info(-1, mr, &start, &end);
495 if (ret) {
496 printf("Memreg get info failed, %d\n", ret);
497 return -EINVAL;
498 }
499 debug("0x%llx -- 0x%llx\n", start, end);
500 *addr_start = start;
501 *addr_end = end;
502
503 return 0;
504 }
505
506 return -EINVAL;
507}
508
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300509__weak void board_mem_get_layout(u64 *phys_sdram_1_start,
510 u64 *phys_sdram_1_size,
511 u64 *phys_sdram_2_start,
512 u64 *phys_sdram_2_size)
513{
514 *phys_sdram_1_start = PHYS_SDRAM_1;
515 *phys_sdram_1_size = PHYS_SDRAM_1_SIZE;
516 *phys_sdram_2_start = PHYS_SDRAM_2;
517 *phys_sdram_2_size = PHYS_SDRAM_2_SIZE;
518}
519
Peng Fan4f211a52018-10-18 14:28:21 +0200520phys_size_t get_effective_memsize(void)
521{
522 sc_rm_mr_t mr;
Ye Li7545bd12020-05-05 20:28:38 +0800523 sc_faddr_t start, end, end1, start_aligned;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300524 u64 phys_sdram_1_start, phys_sdram_1_size;
525 u64 phys_sdram_2_start, phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200526 int err;
527
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300528 board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
529 &phys_sdram_2_start, &phys_sdram_2_size);
530
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300531 end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200532 for (mr = 0; mr < 64; mr++) {
533 err = get_owned_memreg(mr, &start, &end);
534 if (!err) {
Ye Li7545bd12020-05-05 20:28:38 +0800535 start_aligned = roundup(start, MEMSTART_ALIGNMENT);
Peng Fan4f211a52018-10-18 14:28:21 +0200536 /* Too small memory region, not use it */
Ye Li7545bd12020-05-05 20:28:38 +0800537 if (start_aligned > end)
Peng Fan4f211a52018-10-18 14:28:21 +0200538 continue;
539
Peng Fan14b4cd22018-10-18 14:28:22 +0200540 /* Find the memory region runs the U-Boot */
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300541 if (start >= phys_sdram_1_start && start <= end1 &&
Simon Glass72cc5382022-10-20 18:22:39 -0600542 (start <= CONFIG_TEXT_BASE &&
543 end >= CONFIG_TEXT_BASE)) {
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300544 if ((end + 1) <=
545 ((sc_faddr_t)phys_sdram_1_start +
546 phys_sdram_1_size))
547 return (end - phys_sdram_1_start + 1);
Peng Fan4f211a52018-10-18 14:28:21 +0200548 else
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300549 return phys_sdram_1_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200550 }
551 }
552 }
553
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300554 return phys_sdram_1_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200555}
556
557int dram_init(void)
558{
559 sc_rm_mr_t mr;
560 sc_faddr_t start, end, end1, end2;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300561 u64 phys_sdram_1_start, phys_sdram_1_size;
562 u64 phys_sdram_2_start, phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200563 int err;
564
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300565 board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
566 &phys_sdram_2_start, &phys_sdram_2_size);
567
568 end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
569 end2 = (sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200570 for (mr = 0; mr < 64; mr++) {
571 err = get_owned_memreg(mr, &start, &end);
572 if (!err) {
573 start = roundup(start, MEMSTART_ALIGNMENT);
574 /* Too small memory region, not use it */
575 if (start > end)
576 continue;
577
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300578 if (start >= phys_sdram_1_start && start <= end1) {
Peng Fan4f211a52018-10-18 14:28:21 +0200579 if ((end + 1) <= end1)
580 gd->ram_size += end - start + 1;
581 else
582 gd->ram_size += end1 - start;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300583 } else if (start >= phys_sdram_2_start &&
584 start <= end2) {
Peng Fan4f211a52018-10-18 14:28:21 +0200585 if ((end + 1) <= end2)
586 gd->ram_size += end - start + 1;
587 else
588 gd->ram_size += end2 - start;
589 }
590 }
591 }
592
593 /* If error, set to the default value */
594 if (!gd->ram_size) {
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300595 gd->ram_size = phys_sdram_1_size;
596 gd->ram_size += phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200597 }
598 return 0;
599}
600
601static void dram_bank_sort(int current_bank)
602{
603 phys_addr_t start;
604 phys_size_t size;
605
606 while (current_bank > 0) {
607 if (gd->bd->bi_dram[current_bank - 1].start >
608 gd->bd->bi_dram[current_bank].start) {
609 start = gd->bd->bi_dram[current_bank - 1].start;
610 size = gd->bd->bi_dram[current_bank - 1].size;
611
612 gd->bd->bi_dram[current_bank - 1].start =
613 gd->bd->bi_dram[current_bank].start;
614 gd->bd->bi_dram[current_bank - 1].size =
615 gd->bd->bi_dram[current_bank].size;
616
617 gd->bd->bi_dram[current_bank].start = start;
618 gd->bd->bi_dram[current_bank].size = size;
619 }
620 current_bank--;
621 }
622}
623
624int dram_init_banksize(void)
625{
626 sc_rm_mr_t mr;
627 sc_faddr_t start, end, end1, end2;
628 int i = 0;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300629 u64 phys_sdram_1_start, phys_sdram_1_size;
630 u64 phys_sdram_2_start, phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200631 int err;
632
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300633 board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
634 &phys_sdram_2_start, &phys_sdram_2_size);
Peng Fan4f211a52018-10-18 14:28:21 +0200635
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300636 end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
637 end2 = (sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200638 for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) {
639 err = get_owned_memreg(mr, &start, &end);
640 if (!err) {
641 start = roundup(start, MEMSTART_ALIGNMENT);
642 if (start > end) /* Small memory region, no use it */
643 continue;
644
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300645 if (start >= phys_sdram_1_start && start <= end1) {
Peng Fan4f211a52018-10-18 14:28:21 +0200646 gd->bd->bi_dram[i].start = start;
647
648 if ((end + 1) <= end1)
649 gd->bd->bi_dram[i].size =
650 end - start + 1;
651 else
652 gd->bd->bi_dram[i].size = end1 - start;
653
654 dram_bank_sort(i);
655 i++;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300656 } else if (start >= phys_sdram_2_start && start <= end2) {
Peng Fan4f211a52018-10-18 14:28:21 +0200657 gd->bd->bi_dram[i].start = start;
658
659 if ((end + 1) <= end2)
660 gd->bd->bi_dram[i].size =
661 end - start + 1;
662 else
663 gd->bd->bi_dram[i].size = end2 - start;
664
665 dram_bank_sort(i);
666 i++;
667 }
668 }
669 }
670
671 /* If error, set to the default value */
672 if (!i) {
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300673 gd->bd->bi_dram[0].start = phys_sdram_1_start;
674 gd->bd->bi_dram[0].size = phys_sdram_1_size;
675 gd->bd->bi_dram[1].start = phys_sdram_2_start;
676 gd->bd->bi_dram[1].size = phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200677 }
678
679 return 0;
680}
681
682static u64 get_block_attrs(sc_faddr_t addr_start)
683{
684 u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE |
685 PTE_BLOCK_PXN | PTE_BLOCK_UXN;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300686 u64 phys_sdram_1_start, phys_sdram_1_size;
687 u64 phys_sdram_2_start, phys_sdram_2_size;
688
689 board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
690 &phys_sdram_2_start, &phys_sdram_2_size);
Peng Fan4f211a52018-10-18 14:28:21 +0200691
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300692 if ((addr_start >= phys_sdram_1_start &&
693 addr_start <= ((sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size)) ||
694 (addr_start >= phys_sdram_2_start &&
695 addr_start <= ((sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size)))
Peng Fan4f211a52018-10-18 14:28:21 +0200696 return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE);
697
698 return attr;
699}
700
701static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end)
702{
703 sc_faddr_t end1, end2;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300704 u64 phys_sdram_1_start, phys_sdram_1_size;
705 u64 phys_sdram_2_start, phys_sdram_2_size;
Peng Fan4f211a52018-10-18 14:28:21 +0200706
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300707 board_mem_get_layout(&phys_sdram_1_start, &phys_sdram_1_size,
708 &phys_sdram_2_start, &phys_sdram_2_size);
Peng Fan4f211a52018-10-18 14:28:21 +0200709
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300710 end1 = (sc_faddr_t)phys_sdram_1_start + phys_sdram_1_size;
711 end2 = (sc_faddr_t)phys_sdram_2_start + phys_sdram_2_size;
712
713 if (addr_start >= phys_sdram_1_start && addr_start <= end1) {
Peng Fan4f211a52018-10-18 14:28:21 +0200714 if ((addr_end + 1) > end1)
715 return end1 - addr_start;
Marcel Ziswilera45585b2020-10-22 11:21:40 +0300716 } else if (addr_start >= phys_sdram_2_start && addr_start <= end2) {
Peng Fan4f211a52018-10-18 14:28:21 +0200717 if ((addr_end + 1) > end2)
718 return end2 - addr_start;
719 }
720
721 return (addr_end - addr_start + 1);
722}
723
724#define MAX_PTE_ENTRIES 512
725#define MAX_MEM_MAP_REGIONS 16
726
727static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS];
728struct mm_region *mem_map = imx8_mem_map;
729
730void enable_caches(void)
731{
732 sc_rm_mr_t mr;
733 sc_faddr_t start, end;
734 int err, i;
735
736 /* Create map for registers access from 0x1c000000 to 0x80000000*/
737 imx8_mem_map[0].virt = 0x1c000000UL;
738 imx8_mem_map[0].phys = 0x1c000000UL;
739 imx8_mem_map[0].size = 0x64000000UL;
740 imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
741 PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN;
742
743 i = 1;
744 for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) {
745 err = get_owned_memreg(mr, &start, &end);
746 if (!err) {
747 imx8_mem_map[i].virt = start;
748 imx8_mem_map[i].phys = start;
749 imx8_mem_map[i].size = get_block_size(start, end);
750 imx8_mem_map[i].attrs = get_block_attrs(start);
751 i++;
752 }
753 }
754
755 if (i < MAX_MEM_MAP_REGIONS) {
756 imx8_mem_map[i].size = 0;
757 imx8_mem_map[i].attrs = 0;
758 } else {
759 puts("Error, need more MEM MAP REGIONS reserved\n");
760 icache_enable();
761 return;
762 }
763
764 for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) {
765 debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n",
766 i, imx8_mem_map[i].virt, imx8_mem_map[i].phys,
767 imx8_mem_map[i].size, imx8_mem_map[i].attrs);
768 }
769
770 icache_enable();
771 dcache_enable();
772}
773
Trevor Woerner43ec7e02019-05-03 09:41:00 -0400774#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
Peng Fan4f211a52018-10-18 14:28:21 +0200775u64 get_page_table_size(void)
776{
777 u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64);
778 u64 size = 0;
779
780 /*
781 * For each memory region, the max table size:
782 * 2 level 3 tables + 2 level 2 tables + 1 level 1 table
783 */
784 size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt;
785
786 /*
787 * We need to duplicate our page table once to have an emergency pt to
788 * resort to when splitting page tables later on
789 */
790 size *= 2;
791
792 /*
793 * We may need to split page tables later on if dcache settings change,
794 * so reserve up to 4 (random pick) page tables for that.
795 */
796 size += one_pt * 4;
797
798 return size;
799}
800#endif
Anatolij Gustschin05b354b2018-10-18 14:28:23 +0200801
Peng Fan303324d2019-08-26 08:12:23 +0000802#if defined(CONFIG_IMX8QM)
803#define FUSE_MAC0_WORD0 452
804#define FUSE_MAC0_WORD1 453
805#define FUSE_MAC1_WORD0 454
806#define FUSE_MAC1_WORD1 455
807#elif defined(CONFIG_IMX8QXP)
Anatolij Gustschin05b354b2018-10-18 14:28:23 +0200808#define FUSE_MAC0_WORD0 708
809#define FUSE_MAC0_WORD1 709
810#define FUSE_MAC1_WORD0 710
811#define FUSE_MAC1_WORD1 711
Peng Fan303324d2019-08-26 08:12:23 +0000812#endif
Anatolij Gustschin05b354b2018-10-18 14:28:23 +0200813
814void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
815{
816 u32 word[2], val[2] = {};
817 int i, ret;
818
819 if (dev_id == 0) {
820 word[0] = FUSE_MAC0_WORD0;
821 word[1] = FUSE_MAC0_WORD1;
822 } else {
823 word[0] = FUSE_MAC1_WORD0;
824 word[1] = FUSE_MAC1_WORD1;
825 }
826
827 for (i = 0; i < 2; i++) {
828 ret = sc_misc_otp_fuse_read(-1, word[i], &val[i]);
829 if (ret < 0)
830 goto err;
831 }
832
833 mac[0] = val[0];
834 mac[1] = val[0] >> 8;
835 mac[2] = val[0] >> 16;
836 mac[3] = val[0] >> 24;
837 mac[4] = val[1];
838 mac[5] = val[1] >> 8;
839
840 debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n",
841 __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
842 return;
843err:
844 printf("%s: fuse %d, err: %d\n", __func__, word[i], ret);
845}
Anatolij Gustschin9b39be92018-10-18 14:28:24 +0200846
Anatolij Gustschin9b39be92018-10-18 14:28:24 +0200847u32 get_cpu_rev(void)
848{
849 u32 id = 0, rev = 0;
850 int ret;
851
852 ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id);
853 if (ret)
854 return 0;
855
856 rev = (id >> 5) & 0xf;
857 id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */
858
859 return (id << 12) | rev;
860}
Ye Lic3169bd2020-05-05 20:28:42 +0800861
862void board_boot_order(u32 *spl_boot_list)
863{
864 spl_boot_list[0] = spl_boot_device();
865
866 if (spl_boot_list[0] == BOOT_DEVICE_SPI) {
867 /* Check whether we own the flexspi0, if not, use NOR boot */
868 if (!sc_rm_is_resource_owned(-1, SC_R_FSPI_0))
869 spl_boot_list[0] = BOOT_DEVICE_NOR;
870 }
871}
Peng Fan2d65a162020-05-05 20:28:43 +0800872
873bool m4_parts_booted(void)
874{
875 sc_rm_pt_t m4_parts[2];
876 int err;
877
878 err = sc_rm_get_resource_owner(-1, SC_R_M4_0_PID0, &m4_parts[0]);
879 if (err) {
880 printf("%s get resource [%d] owner error: %d\n", __func__,
881 SC_R_M4_0_PID0, err);
882 return false;
883 }
884
885 if (sc_pm_is_partition_started(-1, m4_parts[0]))
886 return true;
887
888 if (is_imx8qm()) {
889 err = sc_rm_get_resource_owner(-1, SC_R_M4_1_PID0, &m4_parts[1]);
890 if (err) {
891 printf("%s get resource [%d] owner error: %d\n",
892 __func__, SC_R_M4_1_PID0, err);
893 return false;
894 }
895
896 if (sc_pm_is_partition_started(-1, m4_parts[1]))
897 return true;
898 }
899
900 return false;
901}