160d33fcdSPeng Fan // SPDX-License-Identifier: GPL-2.0+ 260d33fcdSPeng Fan /* 360d33fcdSPeng Fan * Copyright 2018 NXP 460d33fcdSPeng Fan */ 560d33fcdSPeng Fan 660d33fcdSPeng Fan #include <common.h> 760d33fcdSPeng Fan #include <clk.h> 82fdb1a1dSAnatolij Gustschin #include <cpu.h> 960d33fcdSPeng Fan #include <dm.h> 1060d33fcdSPeng Fan #include <dm/device-internal.h> 1160d33fcdSPeng Fan #include <dm/lists.h> 1260d33fcdSPeng Fan #include <dm/uclass.h> 1360d33fcdSPeng Fan #include <errno.h> 1460d33fcdSPeng Fan #include <asm/arch/sci/sci.h> 158aa1505bSPeng Fan #include <asm/arch/sys_proto.h> 1660d33fcdSPeng Fan #include <asm/arch-imx/cpu.h> 1760d33fcdSPeng Fan #include <asm/armv8/cpu.h> 18930b5952SPeng Fan #include <asm/armv8/mmu.h> 198aa1505bSPeng Fan #include <asm/mach-imx/boot_mode.h> 2060d33fcdSPeng Fan 2160d33fcdSPeng Fan DECLARE_GLOBAL_DATA_PTR; 2260d33fcdSPeng Fan 231ef20a3dSPeng Fan #define BT_PASSOVER_TAG 0x504F 241ef20a3dSPeng Fan struct pass_over_info_t *get_pass_over_info(void) 251ef20a3dSPeng Fan { 261ef20a3dSPeng Fan struct pass_over_info_t *p = 271ef20a3dSPeng Fan (struct pass_over_info_t *)PASS_OVER_INFO_ADDR; 281ef20a3dSPeng Fan 291ef20a3dSPeng Fan if (p->barker != BT_PASSOVER_TAG || 301ef20a3dSPeng Fan p->len != sizeof(struct pass_over_info_t)) 311ef20a3dSPeng Fan return NULL; 321ef20a3dSPeng Fan 331ef20a3dSPeng Fan return p; 341ef20a3dSPeng Fan } 351ef20a3dSPeng Fan 361ef20a3dSPeng Fan int arch_cpu_init(void) 371ef20a3dSPeng Fan { 38*9382f73bSPeng Fan #ifdef CONFIG_SPL_BUILD 39*9382f73bSPeng Fan struct pass_over_info_t *pass_over; 401ef20a3dSPeng Fan 41*9382f73bSPeng Fan if (is_soc_rev(CHIP_REV_A)) { 42*9382f73bSPeng Fan pass_over = get_pass_over_info(); 431ef20a3dSPeng Fan if (pass_over && pass_over->g_ap_mu == 0) { 441ef20a3dSPeng Fan /* 451ef20a3dSPeng Fan * When ap_mu is 0, means the U-Boot booted 461ef20a3dSPeng Fan * from first container 471ef20a3dSPeng Fan */ 481ef20a3dSPeng Fan sc_misc_boot_status(-1, SC_MISC_BOOT_STATUS_SUCCESS); 491ef20a3dSPeng Fan } 50*9382f73bSPeng Fan } 51*9382f73bSPeng Fan #endif 521ef20a3dSPeng Fan 531ef20a3dSPeng Fan return 0; 541ef20a3dSPeng Fan } 551ef20a3dSPeng Fan 561ef20a3dSPeng Fan int arch_cpu_init_dm(void) 571ef20a3dSPeng Fan { 581ef20a3dSPeng Fan struct udevice *devp; 591ef20a3dSPeng Fan int node, ret; 601ef20a3dSPeng Fan 611ef20a3dSPeng Fan node = fdt_node_offset_by_compatible(gd->fdt_blob, -1, "fsl,imx8-mu"); 621ef20a3dSPeng Fan ret = device_bind_driver_to_node(gd->dm_root, "imx8_scu", "imx8_scu", 631ef20a3dSPeng Fan offset_to_ofnode(node), &devp); 641ef20a3dSPeng Fan 651ef20a3dSPeng Fan if (ret) { 661ef20a3dSPeng Fan printf("could not find scu %d\n", ret); 671ef20a3dSPeng Fan return ret; 681ef20a3dSPeng Fan } 691ef20a3dSPeng Fan 701ef20a3dSPeng Fan ret = device_probe(devp); 711ef20a3dSPeng Fan if (ret) { 721ef20a3dSPeng Fan printf("scu probe failed %d\n", ret); 731ef20a3dSPeng Fan return ret; 741ef20a3dSPeng Fan } 751ef20a3dSPeng Fan 761ef20a3dSPeng Fan return 0; 771ef20a3dSPeng Fan } 781ef20a3dSPeng Fan 798aa1505bSPeng Fan int print_bootinfo(void) 808aa1505bSPeng Fan { 818aa1505bSPeng Fan enum boot_device bt_dev = get_boot_device(); 828aa1505bSPeng Fan 838aa1505bSPeng Fan puts("Boot: "); 848aa1505bSPeng Fan switch (bt_dev) { 858aa1505bSPeng Fan case SD1_BOOT: 868aa1505bSPeng Fan puts("SD0\n"); 878aa1505bSPeng Fan break; 888aa1505bSPeng Fan case SD2_BOOT: 898aa1505bSPeng Fan puts("SD1\n"); 908aa1505bSPeng Fan break; 918aa1505bSPeng Fan case SD3_BOOT: 928aa1505bSPeng Fan puts("SD2\n"); 938aa1505bSPeng Fan break; 948aa1505bSPeng Fan case MMC1_BOOT: 958aa1505bSPeng Fan puts("MMC0\n"); 968aa1505bSPeng Fan break; 978aa1505bSPeng Fan case MMC2_BOOT: 988aa1505bSPeng Fan puts("MMC1\n"); 998aa1505bSPeng Fan break; 1008aa1505bSPeng Fan case MMC3_BOOT: 1018aa1505bSPeng Fan puts("MMC2\n"); 1028aa1505bSPeng Fan break; 1038aa1505bSPeng Fan case FLEXSPI_BOOT: 1048aa1505bSPeng Fan puts("FLEXSPI\n"); 1058aa1505bSPeng Fan break; 1068aa1505bSPeng Fan case SATA_BOOT: 1078aa1505bSPeng Fan puts("SATA\n"); 1088aa1505bSPeng Fan break; 1098aa1505bSPeng Fan case NAND_BOOT: 1108aa1505bSPeng Fan puts("NAND\n"); 1118aa1505bSPeng Fan break; 1128aa1505bSPeng Fan case USB_BOOT: 1138aa1505bSPeng Fan puts("USB\n"); 1148aa1505bSPeng Fan break; 1158aa1505bSPeng Fan default: 1168aa1505bSPeng Fan printf("Unknown device %u\n", bt_dev); 1178aa1505bSPeng Fan break; 1188aa1505bSPeng Fan } 1198aa1505bSPeng Fan 1208aa1505bSPeng Fan return 0; 1218aa1505bSPeng Fan } 1228aa1505bSPeng Fan 1238aa1505bSPeng Fan enum boot_device get_boot_device(void) 1248aa1505bSPeng Fan { 1258aa1505bSPeng Fan enum boot_device boot_dev = SD1_BOOT; 1268aa1505bSPeng Fan 1278aa1505bSPeng Fan sc_rsrc_t dev_rsrc; 1288aa1505bSPeng Fan 1298aa1505bSPeng Fan sc_misc_get_boot_dev(-1, &dev_rsrc); 1308aa1505bSPeng Fan 1318aa1505bSPeng Fan switch (dev_rsrc) { 1328aa1505bSPeng Fan case SC_R_SDHC_0: 1338aa1505bSPeng Fan boot_dev = MMC1_BOOT; 1348aa1505bSPeng Fan break; 1358aa1505bSPeng Fan case SC_R_SDHC_1: 1368aa1505bSPeng Fan boot_dev = SD2_BOOT; 1378aa1505bSPeng Fan break; 1388aa1505bSPeng Fan case SC_R_SDHC_2: 1398aa1505bSPeng Fan boot_dev = SD3_BOOT; 1408aa1505bSPeng Fan break; 1418aa1505bSPeng Fan case SC_R_NAND: 1428aa1505bSPeng Fan boot_dev = NAND_BOOT; 1438aa1505bSPeng Fan break; 1448aa1505bSPeng Fan case SC_R_FSPI_0: 1458aa1505bSPeng Fan boot_dev = FLEXSPI_BOOT; 1468aa1505bSPeng Fan break; 1478aa1505bSPeng Fan case SC_R_SATA_0: 1488aa1505bSPeng Fan boot_dev = SATA_BOOT; 1498aa1505bSPeng Fan break; 1508aa1505bSPeng Fan case SC_R_USB_0: 1518aa1505bSPeng Fan case SC_R_USB_1: 1528aa1505bSPeng Fan case SC_R_USB_2: 1538aa1505bSPeng Fan boot_dev = USB_BOOT; 1548aa1505bSPeng Fan break; 1558aa1505bSPeng Fan default: 1568aa1505bSPeng Fan break; 1578aa1505bSPeng Fan } 1588aa1505bSPeng Fan 1598aa1505bSPeng Fan return boot_dev; 1608aa1505bSPeng Fan } 161c1aae21dSPeng Fan 162c1aae21dSPeng Fan #ifdef CONFIG_ENV_IS_IN_MMC 163c1aae21dSPeng Fan __weak int board_mmc_get_env_dev(int devno) 164c1aae21dSPeng Fan { 165c1aae21dSPeng Fan return CONFIG_SYS_MMC_ENV_DEV; 166c1aae21dSPeng Fan } 167c1aae21dSPeng Fan 168c1aae21dSPeng Fan int mmc_get_env_dev(void) 169c1aae21dSPeng Fan { 170c1aae21dSPeng Fan sc_rsrc_t dev_rsrc; 171c1aae21dSPeng Fan int devno; 172c1aae21dSPeng Fan 173c1aae21dSPeng Fan sc_misc_get_boot_dev(-1, &dev_rsrc); 174c1aae21dSPeng Fan 175c1aae21dSPeng Fan switch (dev_rsrc) { 176c1aae21dSPeng Fan case SC_R_SDHC_0: 177c1aae21dSPeng Fan devno = 0; 178c1aae21dSPeng Fan break; 179c1aae21dSPeng Fan case SC_R_SDHC_1: 180c1aae21dSPeng Fan devno = 1; 181c1aae21dSPeng Fan break; 182c1aae21dSPeng Fan case SC_R_SDHC_2: 183c1aae21dSPeng Fan devno = 2; 184c1aae21dSPeng Fan break; 185c1aae21dSPeng Fan default: 186c1aae21dSPeng Fan /* If not boot from sd/mmc, use default value */ 187c1aae21dSPeng Fan return CONFIG_SYS_MMC_ENV_DEV; 188c1aae21dSPeng Fan } 189c1aae21dSPeng Fan 190c1aae21dSPeng Fan return board_mmc_get_env_dev(devno); 191c1aae21dSPeng Fan } 192c1aae21dSPeng Fan #endif 193930b5952SPeng Fan 194930b5952SPeng Fan #define MEMSTART_ALIGNMENT SZ_2M /* Align the memory start with 2MB */ 195930b5952SPeng Fan 196930b5952SPeng Fan static int get_owned_memreg(sc_rm_mr_t mr, sc_faddr_t *addr_start, 197930b5952SPeng Fan sc_faddr_t *addr_end) 198930b5952SPeng Fan { 199930b5952SPeng Fan sc_faddr_t start, end; 200930b5952SPeng Fan int ret; 201930b5952SPeng Fan bool owned; 202930b5952SPeng Fan 203930b5952SPeng Fan owned = sc_rm_is_memreg_owned(-1, mr); 204930b5952SPeng Fan if (owned) { 205930b5952SPeng Fan ret = sc_rm_get_memreg_info(-1, mr, &start, &end); 206930b5952SPeng Fan if (ret) { 207930b5952SPeng Fan printf("Memreg get info failed, %d\n", ret); 208930b5952SPeng Fan return -EINVAL; 209930b5952SPeng Fan } 210930b5952SPeng Fan debug("0x%llx -- 0x%llx\n", start, end); 211930b5952SPeng Fan *addr_start = start; 212930b5952SPeng Fan *addr_end = end; 213930b5952SPeng Fan 214930b5952SPeng Fan return 0; 215930b5952SPeng Fan } 216930b5952SPeng Fan 217930b5952SPeng Fan return -EINVAL; 218930b5952SPeng Fan } 219930b5952SPeng Fan 220930b5952SPeng Fan phys_size_t get_effective_memsize(void) 221930b5952SPeng Fan { 222930b5952SPeng Fan sc_rm_mr_t mr; 223930b5952SPeng Fan sc_faddr_t start, end, end1; 224930b5952SPeng Fan int err; 225930b5952SPeng Fan 226930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; 227930b5952SPeng Fan 228930b5952SPeng Fan for (mr = 0; mr < 64; mr++) { 229930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end); 230930b5952SPeng Fan if (!err) { 231930b5952SPeng Fan start = roundup(start, MEMSTART_ALIGNMENT); 232930b5952SPeng Fan /* Too small memory region, not use it */ 233930b5952SPeng Fan if (start > end) 234930b5952SPeng Fan continue; 235930b5952SPeng Fan 2361ef20a3dSPeng Fan /* Find the memory region runs the U-Boot */ 237930b5952SPeng Fan if (start >= PHYS_SDRAM_1 && start <= end1 && 238930b5952SPeng Fan (start <= CONFIG_SYS_TEXT_BASE && 239930b5952SPeng Fan end >= CONFIG_SYS_TEXT_BASE)) { 240930b5952SPeng Fan if ((end + 1) <= ((sc_faddr_t)PHYS_SDRAM_1 + 241930b5952SPeng Fan PHYS_SDRAM_1_SIZE)) 242930b5952SPeng Fan return (end - PHYS_SDRAM_1 + 1); 243930b5952SPeng Fan else 244930b5952SPeng Fan return PHYS_SDRAM_1_SIZE; 245930b5952SPeng Fan } 246930b5952SPeng Fan } 247930b5952SPeng Fan } 248930b5952SPeng Fan 249930b5952SPeng Fan return PHYS_SDRAM_1_SIZE; 250930b5952SPeng Fan } 251930b5952SPeng Fan 252930b5952SPeng Fan int dram_init(void) 253930b5952SPeng Fan { 254930b5952SPeng Fan sc_rm_mr_t mr; 255930b5952SPeng Fan sc_faddr_t start, end, end1, end2; 256930b5952SPeng Fan int err; 257930b5952SPeng Fan 258930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; 259930b5952SPeng Fan end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; 260930b5952SPeng Fan for (mr = 0; mr < 64; mr++) { 261930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end); 262930b5952SPeng Fan if (!err) { 263930b5952SPeng Fan start = roundup(start, MEMSTART_ALIGNMENT); 264930b5952SPeng Fan /* Too small memory region, not use it */ 265930b5952SPeng Fan if (start > end) 266930b5952SPeng Fan continue; 267930b5952SPeng Fan 268930b5952SPeng Fan if (start >= PHYS_SDRAM_1 && start <= end1) { 269930b5952SPeng Fan if ((end + 1) <= end1) 270930b5952SPeng Fan gd->ram_size += end - start + 1; 271930b5952SPeng Fan else 272930b5952SPeng Fan gd->ram_size += end1 - start; 273930b5952SPeng Fan } else if (start >= PHYS_SDRAM_2 && start <= end2) { 274930b5952SPeng Fan if ((end + 1) <= end2) 275930b5952SPeng Fan gd->ram_size += end - start + 1; 276930b5952SPeng Fan else 277930b5952SPeng Fan gd->ram_size += end2 - start; 278930b5952SPeng Fan } 279930b5952SPeng Fan } 280930b5952SPeng Fan } 281930b5952SPeng Fan 282930b5952SPeng Fan /* If error, set to the default value */ 283930b5952SPeng Fan if (!gd->ram_size) { 284930b5952SPeng Fan gd->ram_size = PHYS_SDRAM_1_SIZE; 285930b5952SPeng Fan gd->ram_size += PHYS_SDRAM_2_SIZE; 286930b5952SPeng Fan } 287930b5952SPeng Fan return 0; 288930b5952SPeng Fan } 289930b5952SPeng Fan 290930b5952SPeng Fan static void dram_bank_sort(int current_bank) 291930b5952SPeng Fan { 292930b5952SPeng Fan phys_addr_t start; 293930b5952SPeng Fan phys_size_t size; 294930b5952SPeng Fan 295930b5952SPeng Fan while (current_bank > 0) { 296930b5952SPeng Fan if (gd->bd->bi_dram[current_bank - 1].start > 297930b5952SPeng Fan gd->bd->bi_dram[current_bank].start) { 298930b5952SPeng Fan start = gd->bd->bi_dram[current_bank - 1].start; 299930b5952SPeng Fan size = gd->bd->bi_dram[current_bank - 1].size; 300930b5952SPeng Fan 301930b5952SPeng Fan gd->bd->bi_dram[current_bank - 1].start = 302930b5952SPeng Fan gd->bd->bi_dram[current_bank].start; 303930b5952SPeng Fan gd->bd->bi_dram[current_bank - 1].size = 304930b5952SPeng Fan gd->bd->bi_dram[current_bank].size; 305930b5952SPeng Fan 306930b5952SPeng Fan gd->bd->bi_dram[current_bank].start = start; 307930b5952SPeng Fan gd->bd->bi_dram[current_bank].size = size; 308930b5952SPeng Fan } 309930b5952SPeng Fan current_bank--; 310930b5952SPeng Fan } 311930b5952SPeng Fan } 312930b5952SPeng Fan 313930b5952SPeng Fan int dram_init_banksize(void) 314930b5952SPeng Fan { 315930b5952SPeng Fan sc_rm_mr_t mr; 316930b5952SPeng Fan sc_faddr_t start, end, end1, end2; 317930b5952SPeng Fan int i = 0; 318930b5952SPeng Fan int err; 319930b5952SPeng Fan 320930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; 321930b5952SPeng Fan end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; 322930b5952SPeng Fan 323930b5952SPeng Fan for (mr = 0; mr < 64 && i < CONFIG_NR_DRAM_BANKS; mr++) { 324930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end); 325930b5952SPeng Fan if (!err) { 326930b5952SPeng Fan start = roundup(start, MEMSTART_ALIGNMENT); 327930b5952SPeng Fan if (start > end) /* Small memory region, no use it */ 328930b5952SPeng Fan continue; 329930b5952SPeng Fan 330930b5952SPeng Fan if (start >= PHYS_SDRAM_1 && start <= end1) { 331930b5952SPeng Fan gd->bd->bi_dram[i].start = start; 332930b5952SPeng Fan 333930b5952SPeng Fan if ((end + 1) <= end1) 334930b5952SPeng Fan gd->bd->bi_dram[i].size = 335930b5952SPeng Fan end - start + 1; 336930b5952SPeng Fan else 337930b5952SPeng Fan gd->bd->bi_dram[i].size = end1 - start; 338930b5952SPeng Fan 339930b5952SPeng Fan dram_bank_sort(i); 340930b5952SPeng Fan i++; 341930b5952SPeng Fan } else if (start >= PHYS_SDRAM_2 && start <= end2) { 342930b5952SPeng Fan gd->bd->bi_dram[i].start = start; 343930b5952SPeng Fan 344930b5952SPeng Fan if ((end + 1) <= end2) 345930b5952SPeng Fan gd->bd->bi_dram[i].size = 346930b5952SPeng Fan end - start + 1; 347930b5952SPeng Fan else 348930b5952SPeng Fan gd->bd->bi_dram[i].size = end2 - start; 349930b5952SPeng Fan 350930b5952SPeng Fan dram_bank_sort(i); 351930b5952SPeng Fan i++; 352930b5952SPeng Fan } 353930b5952SPeng Fan } 354930b5952SPeng Fan } 355930b5952SPeng Fan 356930b5952SPeng Fan /* If error, set to the default value */ 357930b5952SPeng Fan if (!i) { 358930b5952SPeng Fan gd->bd->bi_dram[0].start = PHYS_SDRAM_1; 359930b5952SPeng Fan gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; 360930b5952SPeng Fan gd->bd->bi_dram[1].start = PHYS_SDRAM_2; 361930b5952SPeng Fan gd->bd->bi_dram[1].size = PHYS_SDRAM_2_SIZE; 362930b5952SPeng Fan } 363930b5952SPeng Fan 364930b5952SPeng Fan return 0; 365930b5952SPeng Fan } 366930b5952SPeng Fan 367930b5952SPeng Fan static u64 get_block_attrs(sc_faddr_t addr_start) 368930b5952SPeng Fan { 369930b5952SPeng Fan u64 attr = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | PTE_BLOCK_NON_SHARE | 370930b5952SPeng Fan PTE_BLOCK_PXN | PTE_BLOCK_UXN; 371930b5952SPeng Fan 372930b5952SPeng Fan if ((addr_start >= PHYS_SDRAM_1 && 373930b5952SPeng Fan addr_start <= ((sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE)) || 374930b5952SPeng Fan (addr_start >= PHYS_SDRAM_2 && 375930b5952SPeng Fan addr_start <= ((sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE))) 376930b5952SPeng Fan return (PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE); 377930b5952SPeng Fan 378930b5952SPeng Fan return attr; 379930b5952SPeng Fan } 380930b5952SPeng Fan 381930b5952SPeng Fan static u64 get_block_size(sc_faddr_t addr_start, sc_faddr_t addr_end) 382930b5952SPeng Fan { 383930b5952SPeng Fan sc_faddr_t end1, end2; 384930b5952SPeng Fan 385930b5952SPeng Fan end1 = (sc_faddr_t)PHYS_SDRAM_1 + PHYS_SDRAM_1_SIZE; 386930b5952SPeng Fan end2 = (sc_faddr_t)PHYS_SDRAM_2 + PHYS_SDRAM_2_SIZE; 387930b5952SPeng Fan 388930b5952SPeng Fan if (addr_start >= PHYS_SDRAM_1 && addr_start <= end1) { 389930b5952SPeng Fan if ((addr_end + 1) > end1) 390930b5952SPeng Fan return end1 - addr_start; 391930b5952SPeng Fan } else if (addr_start >= PHYS_SDRAM_2 && addr_start <= end2) { 392930b5952SPeng Fan if ((addr_end + 1) > end2) 393930b5952SPeng Fan return end2 - addr_start; 394930b5952SPeng Fan } 395930b5952SPeng Fan 396930b5952SPeng Fan return (addr_end - addr_start + 1); 397930b5952SPeng Fan } 398930b5952SPeng Fan 399930b5952SPeng Fan #define MAX_PTE_ENTRIES 512 400930b5952SPeng Fan #define MAX_MEM_MAP_REGIONS 16 401930b5952SPeng Fan 402930b5952SPeng Fan static struct mm_region imx8_mem_map[MAX_MEM_MAP_REGIONS]; 403930b5952SPeng Fan struct mm_region *mem_map = imx8_mem_map; 404930b5952SPeng Fan 405930b5952SPeng Fan void enable_caches(void) 406930b5952SPeng Fan { 407930b5952SPeng Fan sc_rm_mr_t mr; 408930b5952SPeng Fan sc_faddr_t start, end; 409930b5952SPeng Fan int err, i; 410930b5952SPeng Fan 411930b5952SPeng Fan /* Create map for registers access from 0x1c000000 to 0x80000000*/ 412930b5952SPeng Fan imx8_mem_map[0].virt = 0x1c000000UL; 413930b5952SPeng Fan imx8_mem_map[0].phys = 0x1c000000UL; 414930b5952SPeng Fan imx8_mem_map[0].size = 0x64000000UL; 415930b5952SPeng Fan imx8_mem_map[0].attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | 416930b5952SPeng Fan PTE_BLOCK_NON_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; 417930b5952SPeng Fan 418930b5952SPeng Fan i = 1; 419930b5952SPeng Fan for (mr = 0; mr < 64 && i < MAX_MEM_MAP_REGIONS; mr++) { 420930b5952SPeng Fan err = get_owned_memreg(mr, &start, &end); 421930b5952SPeng Fan if (!err) { 422930b5952SPeng Fan imx8_mem_map[i].virt = start; 423930b5952SPeng Fan imx8_mem_map[i].phys = start; 424930b5952SPeng Fan imx8_mem_map[i].size = get_block_size(start, end); 425930b5952SPeng Fan imx8_mem_map[i].attrs = get_block_attrs(start); 426930b5952SPeng Fan i++; 427930b5952SPeng Fan } 428930b5952SPeng Fan } 429930b5952SPeng Fan 430930b5952SPeng Fan if (i < MAX_MEM_MAP_REGIONS) { 431930b5952SPeng Fan imx8_mem_map[i].size = 0; 432930b5952SPeng Fan imx8_mem_map[i].attrs = 0; 433930b5952SPeng Fan } else { 434930b5952SPeng Fan puts("Error, need more MEM MAP REGIONS reserved\n"); 435930b5952SPeng Fan icache_enable(); 436930b5952SPeng Fan return; 437930b5952SPeng Fan } 438930b5952SPeng Fan 439930b5952SPeng Fan for (i = 0; i < MAX_MEM_MAP_REGIONS; i++) { 440930b5952SPeng Fan debug("[%d] vir = 0x%llx phys = 0x%llx size = 0x%llx attrs = 0x%llx\n", 441930b5952SPeng Fan i, imx8_mem_map[i].virt, imx8_mem_map[i].phys, 442930b5952SPeng Fan imx8_mem_map[i].size, imx8_mem_map[i].attrs); 443930b5952SPeng Fan } 444930b5952SPeng Fan 445930b5952SPeng Fan icache_enable(); 446930b5952SPeng Fan dcache_enable(); 447930b5952SPeng Fan } 448930b5952SPeng Fan 449930b5952SPeng Fan #ifndef CONFIG_SYS_DCACHE_OFF 450930b5952SPeng Fan u64 get_page_table_size(void) 451930b5952SPeng Fan { 452930b5952SPeng Fan u64 one_pt = MAX_PTE_ENTRIES * sizeof(u64); 453930b5952SPeng Fan u64 size = 0; 454930b5952SPeng Fan 455930b5952SPeng Fan /* 456930b5952SPeng Fan * For each memory region, the max table size: 457930b5952SPeng Fan * 2 level 3 tables + 2 level 2 tables + 1 level 1 table 458930b5952SPeng Fan */ 459930b5952SPeng Fan size = (2 + 2 + 1) * one_pt * MAX_MEM_MAP_REGIONS + one_pt; 460930b5952SPeng Fan 461930b5952SPeng Fan /* 462930b5952SPeng Fan * We need to duplicate our page table once to have an emergency pt to 463930b5952SPeng Fan * resort to when splitting page tables later on 464930b5952SPeng Fan */ 465930b5952SPeng Fan size *= 2; 466930b5952SPeng Fan 467930b5952SPeng Fan /* 468930b5952SPeng Fan * We may need to split page tables later on if dcache settings change, 469930b5952SPeng Fan * so reserve up to 4 (random pick) page tables for that. 470930b5952SPeng Fan */ 471930b5952SPeng Fan size += one_pt * 4; 472930b5952SPeng Fan 473930b5952SPeng Fan return size; 474930b5952SPeng Fan } 475930b5952SPeng Fan #endif 47670b4b49bSAnatolij Gustschin 47770b4b49bSAnatolij Gustschin #define FUSE_MAC0_WORD0 708 47870b4b49bSAnatolij Gustschin #define FUSE_MAC0_WORD1 709 47970b4b49bSAnatolij Gustschin #define FUSE_MAC1_WORD0 710 48070b4b49bSAnatolij Gustschin #define FUSE_MAC1_WORD1 711 48170b4b49bSAnatolij Gustschin 48270b4b49bSAnatolij Gustschin void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) 48370b4b49bSAnatolij Gustschin { 48470b4b49bSAnatolij Gustschin u32 word[2], val[2] = {}; 48570b4b49bSAnatolij Gustschin int i, ret; 48670b4b49bSAnatolij Gustschin 48770b4b49bSAnatolij Gustschin if (dev_id == 0) { 48870b4b49bSAnatolij Gustschin word[0] = FUSE_MAC0_WORD0; 48970b4b49bSAnatolij Gustschin word[1] = FUSE_MAC0_WORD1; 49070b4b49bSAnatolij Gustschin } else { 49170b4b49bSAnatolij Gustschin word[0] = FUSE_MAC1_WORD0; 49270b4b49bSAnatolij Gustschin word[1] = FUSE_MAC1_WORD1; 49370b4b49bSAnatolij Gustschin } 49470b4b49bSAnatolij Gustschin 49570b4b49bSAnatolij Gustschin for (i = 0; i < 2; i++) { 49670b4b49bSAnatolij Gustschin ret = sc_misc_otp_fuse_read(-1, word[i], &val[i]); 49770b4b49bSAnatolij Gustschin if (ret < 0) 49870b4b49bSAnatolij Gustschin goto err; 49970b4b49bSAnatolij Gustschin } 50070b4b49bSAnatolij Gustschin 50170b4b49bSAnatolij Gustschin mac[0] = val[0]; 50270b4b49bSAnatolij Gustschin mac[1] = val[0] >> 8; 50370b4b49bSAnatolij Gustschin mac[2] = val[0] >> 16; 50470b4b49bSAnatolij Gustschin mac[3] = val[0] >> 24; 50570b4b49bSAnatolij Gustschin mac[4] = val[1]; 50670b4b49bSAnatolij Gustschin mac[5] = val[1] >> 8; 50770b4b49bSAnatolij Gustschin 50870b4b49bSAnatolij Gustschin debug("%s: MAC%d: %02x.%02x.%02x.%02x.%02x.%02x\n", 50970b4b49bSAnatolij Gustschin __func__, dev_id, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 51070b4b49bSAnatolij Gustschin return; 51170b4b49bSAnatolij Gustschin err: 51270b4b49bSAnatolij Gustschin printf("%s: fuse %d, err: %d\n", __func__, word[i], ret); 51370b4b49bSAnatolij Gustschin } 5142fdb1a1dSAnatolij Gustschin 5152fdb1a1dSAnatolij Gustschin u32 get_cpu_rev(void) 5162fdb1a1dSAnatolij Gustschin { 5172fdb1a1dSAnatolij Gustschin u32 id = 0, rev = 0; 5182fdb1a1dSAnatolij Gustschin int ret; 5192fdb1a1dSAnatolij Gustschin 5202fdb1a1dSAnatolij Gustschin ret = sc_misc_get_control(-1, SC_R_SYSTEM, SC_C_ID, &id); 5212fdb1a1dSAnatolij Gustschin if (ret) 5222fdb1a1dSAnatolij Gustschin return 0; 5232fdb1a1dSAnatolij Gustschin 5242fdb1a1dSAnatolij Gustschin rev = (id >> 5) & 0xf; 5252fdb1a1dSAnatolij Gustschin id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */ 5262fdb1a1dSAnatolij Gustschin 5272fdb1a1dSAnatolij Gustschin return (id << 12) | rev; 5282fdb1a1dSAnatolij Gustschin } 5292fdb1a1dSAnatolij Gustschin 530*9382f73bSPeng Fan #if CONFIG_IS_ENABLED(CPU) 531*9382f73bSPeng Fan struct cpu_imx_platdata { 532*9382f73bSPeng Fan const char *name; 533*9382f73bSPeng Fan const char *rev; 534*9382f73bSPeng Fan const char *type; 535*9382f73bSPeng Fan u32 cpurev; 536*9382f73bSPeng Fan u32 freq_mhz; 537*9382f73bSPeng Fan }; 538*9382f73bSPeng Fan 5392fdb1a1dSAnatolij Gustschin const char *get_imx8_type(u32 imxtype) 5402fdb1a1dSAnatolij Gustschin { 5412fdb1a1dSAnatolij Gustschin switch (imxtype) { 5422fdb1a1dSAnatolij Gustschin case MXC_CPU_IMX8QXP: 5432fdb1a1dSAnatolij Gustschin case MXC_CPU_IMX8QXP_A0: 5442fdb1a1dSAnatolij Gustschin return "QXP"; 5452fdb1a1dSAnatolij Gustschin default: 5462fdb1a1dSAnatolij Gustschin return "??"; 5472fdb1a1dSAnatolij Gustschin } 5482fdb1a1dSAnatolij Gustschin } 5492fdb1a1dSAnatolij Gustschin 5502fdb1a1dSAnatolij Gustschin const char *get_imx8_rev(u32 rev) 5512fdb1a1dSAnatolij Gustschin { 5522fdb1a1dSAnatolij Gustschin switch (rev) { 5532fdb1a1dSAnatolij Gustschin case CHIP_REV_A: 5542fdb1a1dSAnatolij Gustschin return "A"; 5552fdb1a1dSAnatolij Gustschin case CHIP_REV_B: 5562fdb1a1dSAnatolij Gustschin return "B"; 5572fdb1a1dSAnatolij Gustschin default: 5582fdb1a1dSAnatolij Gustschin return "?"; 5592fdb1a1dSAnatolij Gustschin } 5602fdb1a1dSAnatolij Gustschin } 5612fdb1a1dSAnatolij Gustschin 5622fdb1a1dSAnatolij Gustschin const char *get_core_name(void) 5632fdb1a1dSAnatolij Gustschin { 5642fdb1a1dSAnatolij Gustschin if (is_cortex_a35()) 5652fdb1a1dSAnatolij Gustschin return "A35"; 5662fdb1a1dSAnatolij Gustschin else if (is_cortex_a53()) 5672fdb1a1dSAnatolij Gustschin return "A53"; 5682fdb1a1dSAnatolij Gustschin else if (is_cortex_a72()) 5692fdb1a1dSAnatolij Gustschin return "A72"; 5702fdb1a1dSAnatolij Gustschin else 5712fdb1a1dSAnatolij Gustschin return "?"; 5722fdb1a1dSAnatolij Gustschin } 5732fdb1a1dSAnatolij Gustschin 5742fdb1a1dSAnatolij Gustschin int cpu_imx_get_desc(struct udevice *dev, char *buf, int size) 5752fdb1a1dSAnatolij Gustschin { 5762fdb1a1dSAnatolij Gustschin struct cpu_imx_platdata *plat = dev_get_platdata(dev); 5772fdb1a1dSAnatolij Gustschin 5782fdb1a1dSAnatolij Gustschin if (size < 100) 5792fdb1a1dSAnatolij Gustschin return -ENOSPC; 5802fdb1a1dSAnatolij Gustschin 581da72574bSPeng Fan snprintf(buf, size, "NXP i.MX8%s Rev%s %s at %u MHz\n", 5822fdb1a1dSAnatolij Gustschin plat->type, plat->rev, plat->name, plat->freq_mhz); 5832fdb1a1dSAnatolij Gustschin 5842fdb1a1dSAnatolij Gustschin return 0; 5852fdb1a1dSAnatolij Gustschin } 5862fdb1a1dSAnatolij Gustschin 5872fdb1a1dSAnatolij Gustschin static int cpu_imx_get_info(struct udevice *dev, struct cpu_info *info) 5882fdb1a1dSAnatolij Gustschin { 5892fdb1a1dSAnatolij Gustschin struct cpu_imx_platdata *plat = dev_get_platdata(dev); 5902fdb1a1dSAnatolij Gustschin 5912fdb1a1dSAnatolij Gustschin info->cpu_freq = plat->freq_mhz * 1000; 5922fdb1a1dSAnatolij Gustschin info->features = BIT(CPU_FEAT_L1_CACHE) | BIT(CPU_FEAT_MMU); 5932fdb1a1dSAnatolij Gustschin return 0; 5942fdb1a1dSAnatolij Gustschin } 5952fdb1a1dSAnatolij Gustschin 5962fdb1a1dSAnatolij Gustschin static int cpu_imx_get_count(struct udevice *dev) 5972fdb1a1dSAnatolij Gustschin { 5982fdb1a1dSAnatolij Gustschin return 4; 5992fdb1a1dSAnatolij Gustschin } 6002fdb1a1dSAnatolij Gustschin 6012fdb1a1dSAnatolij Gustschin static int cpu_imx_get_vendor(struct udevice *dev, char *buf, int size) 6022fdb1a1dSAnatolij Gustschin { 6032fdb1a1dSAnatolij Gustschin snprintf(buf, size, "NXP"); 6042fdb1a1dSAnatolij Gustschin return 0; 6052fdb1a1dSAnatolij Gustschin } 6062fdb1a1dSAnatolij Gustschin 6072fdb1a1dSAnatolij Gustschin static const struct cpu_ops cpu_imx8_ops = { 6082fdb1a1dSAnatolij Gustschin .get_desc = cpu_imx_get_desc, 6092fdb1a1dSAnatolij Gustschin .get_info = cpu_imx_get_info, 6102fdb1a1dSAnatolij Gustschin .get_count = cpu_imx_get_count, 6112fdb1a1dSAnatolij Gustschin .get_vendor = cpu_imx_get_vendor, 6122fdb1a1dSAnatolij Gustschin }; 6132fdb1a1dSAnatolij Gustschin 6142fdb1a1dSAnatolij Gustschin static const struct udevice_id cpu_imx8_ids[] = { 6152fdb1a1dSAnatolij Gustschin { .compatible = "arm,cortex-a35" }, 6162fdb1a1dSAnatolij Gustschin { } 6172fdb1a1dSAnatolij Gustschin }; 6182fdb1a1dSAnatolij Gustschin 6192fdb1a1dSAnatolij Gustschin static int imx8_cpu_probe(struct udevice *dev) 6202fdb1a1dSAnatolij Gustschin { 6212fdb1a1dSAnatolij Gustschin struct cpu_imx_platdata *plat = dev_get_platdata(dev); 6222fdb1a1dSAnatolij Gustschin struct clk cpu_clk; 6232fdb1a1dSAnatolij Gustschin u32 cpurev; 6242fdb1a1dSAnatolij Gustschin int ret; 6252fdb1a1dSAnatolij Gustschin 6262fdb1a1dSAnatolij Gustschin cpurev = get_cpu_rev(); 6272fdb1a1dSAnatolij Gustschin plat->cpurev = cpurev; 6282fdb1a1dSAnatolij Gustschin plat->name = get_core_name(); 6292fdb1a1dSAnatolij Gustschin plat->rev = get_imx8_rev(cpurev & 0xFFF); 6302fdb1a1dSAnatolij Gustschin plat->type = get_imx8_type((cpurev & 0xFF000) >> 12); 6312fdb1a1dSAnatolij Gustschin 6322fdb1a1dSAnatolij Gustschin ret = clk_get_by_index(dev, 0, &cpu_clk); 6332fdb1a1dSAnatolij Gustschin if (ret) { 6342fdb1a1dSAnatolij Gustschin debug("%s: Failed to get CPU clk: %d\n", __func__, ret); 6352fdb1a1dSAnatolij Gustschin return 0; 6362fdb1a1dSAnatolij Gustschin } 6372fdb1a1dSAnatolij Gustschin 6382fdb1a1dSAnatolij Gustschin plat->freq_mhz = clk_get_rate(&cpu_clk) / 1000000; 6392fdb1a1dSAnatolij Gustschin return 0; 6402fdb1a1dSAnatolij Gustschin } 6412fdb1a1dSAnatolij Gustschin 6422fdb1a1dSAnatolij Gustschin U_BOOT_DRIVER(cpu_imx8_drv) = { 6432fdb1a1dSAnatolij Gustschin .name = "imx8x_cpu", 6442fdb1a1dSAnatolij Gustschin .id = UCLASS_CPU, 6452fdb1a1dSAnatolij Gustschin .of_match = cpu_imx8_ids, 6462fdb1a1dSAnatolij Gustschin .ops = &cpu_imx8_ops, 6472fdb1a1dSAnatolij Gustschin .probe = imx8_cpu_probe, 6482fdb1a1dSAnatolij Gustschin .platdata_auto_alloc_size = sizeof(struct cpu_imx_platdata), 6492fdb1a1dSAnatolij Gustschin .flags = DM_FLAG_PRE_RELOC, 6502fdb1a1dSAnatolij Gustschin }; 6512fdb1a1dSAnatolij Gustschin #endif 652