uboot/arch/arm/mach-imx/imx8m/soc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright 2017-2019 NXP
   4 *
   5 * Peng Fan <peng.fan@nxp.com>
   6 */
   7
   8#include <common.h>
   9#include <cpu_func.h>
  10#include <init.h>
  11#include <log.h>
  12#include <asm/arch/imx-regs.h>
  13#include <asm/io.h>
  14#include <asm/arch/clock.h>
  15#include <asm/arch/sys_proto.h>
  16#include <asm/mach-imx/hab.h>
  17#include <asm/mach-imx/boot_mode.h>
  18#include <asm/mach-imx/syscounter.h>
  19#include <asm/ptrace.h>
  20#include <asm/armv8/mmu.h>
  21#include <dm/uclass.h>
  22#include <efi_loader.h>
  23#include <env.h>
  24#include <env_internal.h>
  25#include <errno.h>
  26#include <fdt_support.h>
  27#include <fsl_wdog.h>
  28#include <imx_sip.h>
  29#include <linux/arm-smccc.h>
  30#include <linux/bitops.h>
  31
  32DECLARE_GLOBAL_DATA_PTR;
  33
  34#if defined(CONFIG_IMX_HAB)
  35struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
  36        .bank = 1,
  37        .word = 3,
  38};
  39#endif
  40
  41int timer_init(void)
  42{
  43#ifdef CONFIG_SPL_BUILD
  44        struct sctr_regs *sctr = (struct sctr_regs *)SYSCNT_CTRL_BASE_ADDR;
  45        unsigned long freq = readl(&sctr->cntfid0);
  46
  47        /* Update with accurate clock frequency */
  48        asm volatile("msr cntfrq_el0, %0" : : "r" (freq) : "memory");
  49
  50        clrsetbits_le32(&sctr->cntcr, SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1,
  51                        SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG);
  52#endif
  53
  54        gd->arch.tbl = 0;
  55        gd->arch.tbu = 0;
  56
  57        return 0;
  58}
  59
  60void enable_tzc380(void)
  61{
  62        struct iomuxc_gpr_base_regs *gpr =
  63                (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
  64
  65        /* Enable TZASC and lock setting */
  66        setbits_le32(&gpr->gpr[10], GPR_TZASC_EN);
  67        setbits_le32(&gpr->gpr[10], GPR_TZASC_EN_LOCK);
  68        if (is_imx8mm() || is_imx8mn() || is_imx8mp())
  69                setbits_le32(&gpr->gpr[10], BIT(1));
  70        /*
  71         * set Region 0 attribute to allow secure and non-secure
  72         * read/write permission. Found some masters like usb dwc3
  73         * controllers can't work with secure memory.
  74         */
  75        writel(0xf0000000, TZASC_BASE_ADDR + 0x108);
  76}
  77
  78void set_wdog_reset(struct wdog_regs *wdog)
  79{
  80        /*
  81         * Output WDOG_B signal to reset external pmic or POR_B decided by
  82         * the board design. Without external reset, the peripherals/DDR/
  83         * PMIC are not reset, that may cause system working abnormal.
  84         * WDZST bit is write-once only bit. Align this bit in kernel,
  85         * otherwise kernel code will have no chance to set this bit.
  86         */
  87        setbits_le16(&wdog->wcr, WDOG_WDT_MASK | WDOG_WDZST_MASK);
  88}
  89
  90static struct mm_region imx8m_mem_map[] = {
  91        {
  92                /* ROM */
  93                .virt = 0x0UL,
  94                .phys = 0x0UL,
  95                .size = 0x100000UL,
  96                .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
  97                         PTE_BLOCK_OUTER_SHARE
  98        }, {
  99                /* CAAM */
 100                .virt = 0x100000UL,
 101                .phys = 0x100000UL,
 102                .size = 0x8000UL,
 103                .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 104                         PTE_BLOCK_NON_SHARE |
 105                         PTE_BLOCK_PXN | PTE_BLOCK_UXN
 106        }, {
 107                /* TCM */
 108                .virt = 0x7C0000UL,
 109                .phys = 0x7C0000UL,
 110                .size = 0x80000UL,
 111                .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 112                         PTE_BLOCK_NON_SHARE |
 113                         PTE_BLOCK_PXN | PTE_BLOCK_UXN
 114        }, {
 115                /* OCRAM */
 116                .virt = 0x900000UL,
 117                .phys = 0x900000UL,
 118                .size = 0x200000UL,
 119                .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 120                         PTE_BLOCK_OUTER_SHARE
 121        }, {
 122                /* AIPS */
 123                .virt = 0xB00000UL,
 124                .phys = 0xB00000UL,
 125                .size = 0x3f500000UL,
 126                .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 127                         PTE_BLOCK_NON_SHARE |
 128                         PTE_BLOCK_PXN | PTE_BLOCK_UXN
 129        }, {
 130                /* DRAM1 */
 131                .virt = 0x40000000UL,
 132                .phys = 0x40000000UL,
 133                .size = PHYS_SDRAM_SIZE,
 134                .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 135                         PTE_BLOCK_OUTER_SHARE
 136#ifdef PHYS_SDRAM_2_SIZE
 137        }, {
 138                /* DRAM2 */
 139                .virt = 0x100000000UL,
 140                .phys = 0x100000000UL,
 141                .size = PHYS_SDRAM_2_SIZE,
 142                .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 143                         PTE_BLOCK_OUTER_SHARE
 144#endif
 145        }, {
 146                /* empty entrie to split table entry 5 if needed when TEEs are used */
 147                0,
 148        }, {
 149                /* List terminator */
 150                0,
 151        }
 152};
 153
 154struct mm_region *mem_map = imx8m_mem_map;
 155
 156void enable_caches(void)
 157{
 158        /* If OPTEE runs, remove OPTEE memory from MMU table to avoid speculative prefetch */
 159        if (rom_pointer[1]) {
 160                /*
 161                 * TEE are loaded, So the ddr bank structures
 162                 * have been modified update mmu table accordingly
 163                 */
 164                int i = 0;
 165                /*
 166                 * please make sure that entry initial value matches
 167                 * imx8m_mem_map for DRAM1
 168                 */
 169                int entry = 5;
 170                u64 attrs = imx8m_mem_map[entry].attrs;
 171
 172                while (i < CONFIG_NR_DRAM_BANKS && entry < 8) {
 173                        if (gd->bd->bi_dram[i].start == 0)
 174                                break;
 175                        imx8m_mem_map[entry].phys = gd->bd->bi_dram[i].start;
 176                        imx8m_mem_map[entry].virt = gd->bd->bi_dram[i].start;
 177                        imx8m_mem_map[entry].size = gd->bd->bi_dram[i].size;
 178                        imx8m_mem_map[entry].attrs = attrs;
 179                        debug("Added memory mapping (%d): %llx %llx\n", entry,
 180                              imx8m_mem_map[entry].phys, imx8m_mem_map[entry].size);
 181                        i++; entry++;
 182                }
 183        }
 184
 185        icache_enable();
 186        dcache_enable();
 187}
 188
 189__weak int board_phys_sdram_size(phys_size_t *size)
 190{
 191        if (!size)
 192                return -EINVAL;
 193
 194        *size = PHYS_SDRAM_SIZE;
 195        return 0;
 196}
 197
 198int dram_init(void)
 199{
 200        phys_size_t sdram_size;
 201        int ret;
 202
 203        ret = board_phys_sdram_size(&sdram_size);
 204        if (ret)
 205                return ret;
 206
 207        /* rom_pointer[1] contains the size of TEE occupies */
 208        if (rom_pointer[1])
 209                gd->ram_size = sdram_size - rom_pointer[1];
 210        else
 211                gd->ram_size = sdram_size;
 212
 213        /* also update the SDRAM size in the mem_map used externally */
 214        imx8m_mem_map[5].size = sdram_size;
 215
 216#ifdef PHYS_SDRAM_2_SIZE
 217        gd->ram_size += PHYS_SDRAM_2_SIZE;
 218#endif
 219
 220        return 0;
 221}
 222
 223int dram_init_banksize(void)
 224{
 225        int bank = 0;
 226        int ret;
 227        phys_size_t sdram_size;
 228
 229        ret = board_phys_sdram_size(&sdram_size);
 230        if (ret)
 231                return ret;
 232
 233        gd->bd->bi_dram[bank].start = PHYS_SDRAM;
 234        if (rom_pointer[1]) {
 235                phys_addr_t optee_start = (phys_addr_t)rom_pointer[0];
 236                phys_size_t optee_size = (size_t)rom_pointer[1];
 237
 238                gd->bd->bi_dram[bank].size = optee_start - gd->bd->bi_dram[bank].start;
 239                if ((optee_start + optee_size) < (PHYS_SDRAM + sdram_size)) {
 240                        if (++bank >= CONFIG_NR_DRAM_BANKS) {
 241                                puts("CONFIG_NR_DRAM_BANKS is not enough\n");
 242                                return -1;
 243                        }
 244
 245                        gd->bd->bi_dram[bank].start = optee_start + optee_size;
 246                        gd->bd->bi_dram[bank].size = PHYS_SDRAM +
 247                                sdram_size - gd->bd->bi_dram[bank].start;
 248                }
 249        } else {
 250                gd->bd->bi_dram[bank].size = sdram_size;
 251        }
 252
 253#ifdef PHYS_SDRAM_2_SIZE
 254        if (++bank >= CONFIG_NR_DRAM_BANKS) {
 255                puts("CONFIG_NR_DRAM_BANKS is not enough for SDRAM_2\n");
 256                return -1;
 257        }
 258        gd->bd->bi_dram[bank].start = PHYS_SDRAM_2;
 259        gd->bd->bi_dram[bank].size = PHYS_SDRAM_2_SIZE;
 260#endif
 261
 262        return 0;
 263}
 264
 265phys_size_t get_effective_memsize(void)
 266{
 267        /* return the first bank as effective memory */
 268        if (rom_pointer[1])
 269                return ((phys_addr_t)rom_pointer[0] - PHYS_SDRAM);
 270
 271#ifdef PHYS_SDRAM_2_SIZE
 272        return gd->ram_size - PHYS_SDRAM_2_SIZE;
 273#else
 274        return gd->ram_size;
 275#endif
 276}
 277
 278static u32 get_cpu_variant_type(u32 type)
 279{
 280        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 281        struct fuse_bank *bank = &ocotp->bank[1];
 282        struct fuse_bank1_regs *fuse =
 283                (struct fuse_bank1_regs *)bank->fuse_regs;
 284
 285        u32 value = readl(&fuse->tester4);
 286
 287        if (type == MXC_CPU_IMX8MQ) {
 288                if ((value & 0x3) == 0x2)
 289                        return MXC_CPU_IMX8MD;
 290                else if (value & 0x200000)
 291                        return MXC_CPU_IMX8MQL;
 292
 293        } else if (type == MXC_CPU_IMX8MM) {
 294                switch (value & 0x3) {
 295                case 2:
 296                        if (value & 0x1c0000)
 297                                return MXC_CPU_IMX8MMDL;
 298                        else
 299                                return MXC_CPU_IMX8MMD;
 300                case 3:
 301                        if (value & 0x1c0000)
 302                                return MXC_CPU_IMX8MMSL;
 303                        else
 304                                return MXC_CPU_IMX8MMS;
 305                default:
 306                        if (value & 0x1c0000)
 307                                return MXC_CPU_IMX8MML;
 308                        break;
 309                }
 310        } else if (type == MXC_CPU_IMX8MN) {
 311                switch (value & 0x3) {
 312                case 2:
 313                        if (value & 0x1000000)
 314                                return MXC_CPU_IMX8MNDL;
 315                        else
 316                                return MXC_CPU_IMX8MND;
 317                case 3:
 318                        if (value & 0x1000000)
 319                                return MXC_CPU_IMX8MNSL;
 320                        else
 321                                return MXC_CPU_IMX8MNS;
 322                default:
 323                        if (value & 0x1000000)
 324                                return MXC_CPU_IMX8MNL;
 325                        break;
 326                }
 327        } else if (type == MXC_CPU_IMX8MP) {
 328                u32 value0 = readl(&fuse->tester3);
 329                u32 flag = 0;
 330
 331                if ((value0 & 0xc0000) == 0x80000)
 332                        return MXC_CPU_IMX8MPD;
 333
 334                        /* vpu disabled */
 335                if ((value0 & 0x43000000) == 0x43000000)
 336                        flag = 1;
 337
 338                /* npu disabled*/
 339                if ((value & 0x8) == 0x8)
 340                        flag |= (1 << 1);
 341
 342                /* isp disabled */
 343                if ((value & 0x3) == 0x3)
 344                        flag |= (1 << 2);
 345
 346                switch (flag) {
 347                case 7:
 348                        return MXC_CPU_IMX8MPL;
 349                case 2:
 350                        return MXC_CPU_IMX8MP6;
 351                default:
 352                        break;
 353                }
 354
 355        }
 356
 357        return type;
 358}
 359
 360u32 get_cpu_rev(void)
 361{
 362        struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
 363        u32 reg = readl(&ana_pll->digprog);
 364        u32 type = (reg >> 16) & 0xff;
 365        u32 major_low = (reg >> 8) & 0xff;
 366        u32 rom_version;
 367
 368        reg &= 0xff;
 369
 370        /* iMX8MP */
 371        if (major_low == 0x43) {
 372                type = get_cpu_variant_type(MXC_CPU_IMX8MP);
 373        } else if (major_low == 0x42) {
 374                /* iMX8MN */
 375                type = get_cpu_variant_type(MXC_CPU_IMX8MN);
 376        } else if (major_low == 0x41) {
 377                type = get_cpu_variant_type(MXC_CPU_IMX8MM);
 378        } else {
 379                if (reg == CHIP_REV_1_0) {
 380                        /*
 381                         * For B0 chip, the DIGPROG is not updated,
 382                         * it is still TO1.0. we have to check ROM
 383                         * version or OCOTP_READ_FUSE_DATA.
 384                         * 0xff0055aa is magic number for B1.
 385                         */
 386                        if (readl((void __iomem *)(OCOTP_BASE_ADDR + 0x40)) == 0xff0055aa) {
 387                                reg = CHIP_REV_2_1;
 388                        } else {
 389                                rom_version =
 390                                        readl((void __iomem *)ROM_VERSION_A0);
 391                                if (rom_version != CHIP_REV_1_0) {
 392                                        rom_version = readl((void __iomem *)ROM_VERSION_B0);
 393                                        rom_version &= 0xff;
 394                                        if (rom_version == CHIP_REV_2_0)
 395                                                reg = CHIP_REV_2_0;
 396                                }
 397                        }
 398                }
 399
 400                type = get_cpu_variant_type(type);
 401        }
 402
 403        return (type << 12) | reg;
 404}
 405
 406static void imx_set_wdog_powerdown(bool enable)
 407{
 408        struct wdog_regs *wdog1 = (struct wdog_regs *)WDOG1_BASE_ADDR;
 409        struct wdog_regs *wdog2 = (struct wdog_regs *)WDOG2_BASE_ADDR;
 410        struct wdog_regs *wdog3 = (struct wdog_regs *)WDOG3_BASE_ADDR;
 411
 412        /* Write to the PDE (Power Down Enable) bit */
 413        writew(enable, &wdog1->wmcr);
 414        writew(enable, &wdog2->wmcr);
 415        writew(enable, &wdog3->wmcr);
 416}
 417
 418int arch_cpu_init_dm(void)
 419{
 420        struct udevice *dev;
 421        int ret;
 422
 423        if (CONFIG_IS_ENABLED(CLK)) {
 424                ret = uclass_get_device_by_name(UCLASS_CLK,
 425                                                "clock-controller@30380000",
 426                                                &dev);
 427                if (ret < 0) {
 428                        printf("Failed to find clock node. Check device tree\n");
 429                        return ret;
 430                }
 431        }
 432
 433        return 0;
 434}
 435
 436int arch_cpu_init(void)
 437{
 438        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 439        /*
 440         * ROM might disable clock for SCTR,
 441         * enable the clock before timer_init.
 442         */
 443        if (IS_ENABLED(CONFIG_SPL_BUILD))
 444                clock_enable(CCGR_SCTR, 1);
 445        /*
 446         * Init timer at very early state, because sscg pll setting
 447         * will use it
 448         */
 449        timer_init();
 450
 451        if (IS_ENABLED(CONFIG_SPL_BUILD)) {
 452                clock_init();
 453                imx_set_wdog_powerdown(false);
 454
 455                if (is_imx8md() || is_imx8mmd() || is_imx8mmdl() || is_imx8mms() ||
 456                    is_imx8mmsl() || is_imx8mnd() || is_imx8mndl() || is_imx8mns() ||
 457                    is_imx8mnsl() || is_imx8mpd()) {
 458                        /* Power down cpu core 1, 2 and 3 for iMX8M Dual core or Single core */
 459                        struct pgc_reg *pgc_core1 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x840);
 460                        struct pgc_reg *pgc_core2 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x880);
 461                        struct pgc_reg *pgc_core3 = (struct pgc_reg *)(GPC_BASE_ADDR + 0x8C0);
 462                        struct gpc_reg *gpc = (struct gpc_reg *)GPC_BASE_ADDR;
 463
 464                        writel(0x1, &pgc_core2->pgcr);
 465                        writel(0x1, &pgc_core3->pgcr);
 466                        if (is_imx8mms() || is_imx8mmsl() || is_imx8mns() || is_imx8mnsl()) {
 467                                writel(0x1, &pgc_core1->pgcr);
 468                                writel(0xE, &gpc->cpu_pgc_dn_trg);
 469                        } else {
 470                                writel(0xC, &gpc->cpu_pgc_dn_trg);
 471                        }
 472                }
 473        }
 474
 475        if (is_imx8mq()) {
 476                clock_enable(CCGR_OCOTP, 1);
 477                if (readl(&ocotp->ctrl) & 0x200)
 478                        writel(0x200, &ocotp->ctrl_clr);
 479        }
 480
 481        return 0;
 482}
 483
 484#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
 485struct rom_api *g_rom_api = (struct rom_api *)0x980;
 486
 487enum boot_device get_boot_device(void)
 488{
 489        volatile gd_t *pgd = gd;
 490        int ret;
 491        u32 boot;
 492        u16 boot_type;
 493        u8 boot_instance;
 494        enum boot_device boot_dev = SD1_BOOT;
 495
 496        ret = g_rom_api->query_boot_infor(QUERY_BT_DEV, &boot,
 497                                          ((uintptr_t)&boot) ^ QUERY_BT_DEV);
 498        gd = pgd;
 499
 500        if (ret != ROM_API_OKAY) {
 501                puts("ROMAPI: failure at query_boot_info\n");
 502                return -1;
 503        }
 504
 505        boot_type = boot >> 16;
 506        boot_instance = (boot >> 8) & 0xff;
 507
 508        switch (boot_type) {
 509        case BT_DEV_TYPE_SD:
 510                boot_dev = boot_instance + SD1_BOOT;
 511                break;
 512        case BT_DEV_TYPE_MMC:
 513                boot_dev = boot_instance + MMC1_BOOT;
 514                break;
 515        case BT_DEV_TYPE_NAND:
 516                boot_dev = NAND_BOOT;
 517                break;
 518        case BT_DEV_TYPE_FLEXSPINOR:
 519                boot_dev = QSPI_BOOT;
 520                break;
 521        case BT_DEV_TYPE_USB:
 522                boot_dev = USB_BOOT;
 523                break;
 524        default:
 525                break;
 526        }
 527
 528        return boot_dev;
 529}
 530#endif
 531
 532bool is_usb_boot(void)
 533{
 534        return get_boot_device() == USB_BOOT;
 535}
 536
 537#ifdef CONFIG_OF_SYSTEM_SETUP
 538bool check_fdt_new_path(void *blob)
 539{
 540        const char *soc_path = "/soc@0";
 541        int nodeoff;
 542
 543        nodeoff = fdt_path_offset(blob, soc_path);
 544        if (nodeoff < 0)
 545                return false;
 546
 547        return true;
 548}
 549
 550static int disable_fdt_nodes(void *blob, const char *const nodes_path[], int size_array)
 551{
 552        int i = 0;
 553        int rc;
 554        int nodeoff;
 555        const char *status = "disabled";
 556
 557        for (i = 0; i < size_array; i++) {
 558                nodeoff = fdt_path_offset(blob, nodes_path[i]);
 559                if (nodeoff < 0)
 560                        continue; /* Not found, skip it */
 561
 562                printf("Found %s node\n", nodes_path[i]);
 563
 564add_status:
 565                rc = fdt_setprop(blob, nodeoff, "status", status, strlen(status) + 1);
 566                if (rc) {
 567                        if (rc == -FDT_ERR_NOSPACE) {
 568                                rc = fdt_increase_size(blob, 512);
 569                                if (!rc)
 570                                        goto add_status;
 571                        }
 572                        printf("Unable to update property %s:%s, err=%s\n",
 573                               nodes_path[i], "status", fdt_strerror(rc));
 574                } else {
 575                        printf("Modify %s:%s disabled\n",
 576                               nodes_path[i], "status");
 577                }
 578        }
 579
 580        return 0;
 581}
 582
 583#ifdef CONFIG_IMX8MQ
 584bool check_dcss_fused(void)
 585{
 586        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 587        struct fuse_bank *bank = &ocotp->bank[1];
 588        struct fuse_bank1_regs *fuse =
 589                (struct fuse_bank1_regs *)bank->fuse_regs;
 590        u32 value = readl(&fuse->tester4);
 591
 592        if (value & 0x4000000)
 593                return true;
 594
 595        return false;
 596}
 597
 598static int disable_mipi_dsi_nodes(void *blob)
 599{
 600        static const char * const nodes_path[] = {
 601                "/mipi_dsi@30A00000",
 602                "/mipi_dsi_bridge@30A00000",
 603                "/dsi_phy@30A00300",
 604                "/soc@0/bus@30800000/mipi_dsi@30a00000",
 605                "/soc@0/bus@30800000/dphy@30a00300"
 606        };
 607
 608        return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
 609}
 610
 611static int disable_dcss_nodes(void *blob)
 612{
 613        static const char * const nodes_path[] = {
 614                "/dcss@0x32e00000",
 615                "/dcss@32e00000",
 616                "/hdmi@32c00000",
 617                "/hdmi_cec@32c33800",
 618                "/hdmi_drm@32c00000",
 619                "/display-subsystem",
 620                "/sound-hdmi",
 621                "/sound-hdmi-arc",
 622                "/soc@0/bus@32c00000/display-controller@32e00000",
 623                "/soc@0/bus@32c00000/hdmi@32c00000",
 624        };
 625
 626        return disable_fdt_nodes(blob, nodes_path, ARRAY_SIZE(nodes_path));
 627}
 628
 629static int check_mipi_dsi_nodes(void *blob)
 630{
 631        static const char * const lcdif_path[] = {
 632                "/lcdif@30320000",
 633                "/soc@0/bus@30000000/lcdif@30320000"
 634        };
 635        static const char * const mipi_dsi_path[] = {
 636                "/mipi_dsi@30A00000",
 637                "/soc@0/bus@30800000/mipi_dsi@30a00000"
 638        };
 639        static const char * const lcdif_ep_path[] = {
 640                "/lcdif@30320000/port@0/mipi-dsi-endpoint",
 641                "/soc@0/bus@30000000/lcdif@30320000/port@0/endpoint"
 642        };
 643        static const char * const mipi_dsi_ep_path[] = {
 644                "/mipi_dsi@30A00000/port@1/endpoint",
 645                "/soc@0/bus@30800000/mipi_dsi@30a00000/ports/port@0/endpoint"
 646        };
 647
 648        int lookup_node;
 649        int nodeoff;
 650        bool new_path = check_fdt_new_path(blob);
 651        int i = new_path ? 1 : 0;
 652
 653        nodeoff = fdt_path_offset(blob, lcdif_path[i]);
 654        if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff)) {
 655                /*
 656                 * If can't find lcdif node or lcdif node is disabled,
 657                 * then disable all mipi dsi, since they only can input
 658                 * from DCSS
 659                 */
 660                return disable_mipi_dsi_nodes(blob);
 661        }
 662
 663        nodeoff = fdt_path_offset(blob, mipi_dsi_path[i]);
 664        if (nodeoff < 0 || !fdtdec_get_is_enabled(blob, nodeoff))
 665                return 0;
 666
 667        nodeoff = fdt_path_offset(blob, lcdif_ep_path[i]);
 668        if (nodeoff < 0) {
 669                /*
 670                 * If can't find lcdif endpoint, then disable all mipi dsi,
 671                 * since they only can input from DCSS
 672                 */
 673                return disable_mipi_dsi_nodes(blob);
 674        }
 675
 676        lookup_node = fdtdec_lookup_phandle(blob, nodeoff, "remote-endpoint");
 677        nodeoff = fdt_path_offset(blob, mipi_dsi_ep_path[i]);
 678
 679        if (nodeoff > 0 && nodeoff == lookup_node)
 680                return 0;
 681
 682        return disable_mipi_dsi_nodes(blob);
 683}
 684#endif
 685
 686int disable_vpu_nodes(void *blob)
 687{
 688        static const char * const nodes_path_8mq[] = {
 689                "/vpu@38300000",
 690                "/soc@0/vpu@38300000"
 691        };
 692
 693        static const char * const nodes_path_8mm[] = {
 694                "/vpu_g1@38300000",
 695                "/vpu_g2@38310000",
 696                "/vpu_h1@38320000"
 697        };
 698
 699        static const char * const nodes_path_8mp[] = {
 700                "/vpu_g1@38300000",
 701                "/vpu_g2@38310000",
 702                "/vpu_vc8000e@38320000"
 703        };
 704
 705        if (is_imx8mq())
 706                return disable_fdt_nodes(blob, nodes_path_8mq, ARRAY_SIZE(nodes_path_8mq));
 707        else if (is_imx8mm())
 708                return disable_fdt_nodes(blob, nodes_path_8mm, ARRAY_SIZE(nodes_path_8mm));
 709        else if (is_imx8mp())
 710                return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
 711        else
 712                return -EPERM;
 713}
 714
 715int disable_gpu_nodes(void *blob)
 716{
 717        static const char * const nodes_path_8mn[] = {
 718                "/gpu@38000000"
 719        };
 720
 721        return disable_fdt_nodes(blob, nodes_path_8mn, ARRAY_SIZE(nodes_path_8mn));
 722}
 723
 724int disable_npu_nodes(void *blob)
 725{
 726        static const char * const nodes_path_8mp[] = {
 727                "/vipsi@38500000"
 728        };
 729
 730        return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
 731}
 732
 733int disable_isp_nodes(void *blob)
 734{
 735        static const char * const nodes_path_8mp[] = {
 736                "/soc@0/bus@32c00000/camera/isp@32e10000",
 737                "/soc@0/bus@32c00000/camera/isp@32e20000"
 738        };
 739
 740        return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
 741}
 742
 743int disable_dsp_nodes(void *blob)
 744{
 745        static const char * const nodes_path_8mp[] = {
 746                "/dsp@3b6e8000"
 747        };
 748
 749        return disable_fdt_nodes(blob, nodes_path_8mp, ARRAY_SIZE(nodes_path_8mp));
 750}
 751
 752static int disable_cpu_nodes(void *blob, u32 disabled_cores)
 753{
 754        static const char * const nodes_path[] = {
 755                "/cpus/cpu@1",
 756                "/cpus/cpu@2",
 757                "/cpus/cpu@3",
 758        };
 759        u32 i = 0;
 760        int rc;
 761        int nodeoff;
 762
 763        if (disabled_cores > 3)
 764                return -EINVAL;
 765
 766        i = 3 - disabled_cores;
 767
 768        for (; i < 3; i++) {
 769                nodeoff = fdt_path_offset(blob, nodes_path[i]);
 770                if (nodeoff < 0)
 771                        continue; /* Not found, skip it */
 772
 773                debug("Found %s node\n", nodes_path[i]);
 774
 775                rc = fdt_del_node(blob, nodeoff);
 776                if (rc < 0) {
 777                        printf("Unable to delete node %s, err=%s\n",
 778                               nodes_path[i], fdt_strerror(rc));
 779                } else {
 780                        printf("Delete node %s\n", nodes_path[i]);
 781                }
 782        }
 783
 784        return 0;
 785}
 786
 787int ft_system_setup(void *blob, struct bd_info *bd)
 788{
 789#ifdef CONFIG_IMX8MQ
 790        int i = 0;
 791        int rc;
 792        int nodeoff;
 793
 794        if (get_boot_device() == USB_BOOT) {
 795                disable_dcss_nodes(blob);
 796
 797                bool new_path = check_fdt_new_path(blob);
 798                int v = new_path ? 1 : 0;
 799                static const char * const usb_dwc3_path[] = {
 800                        "/usb@38100000/dwc3",
 801                        "/soc@0/usb@38100000"
 802                };
 803
 804                nodeoff = fdt_path_offset(blob, usb_dwc3_path[v]);
 805                if (nodeoff >= 0) {
 806                        const char *speed = "high-speed";
 807
 808                        printf("Found %s node\n", usb_dwc3_path[v]);
 809
 810usb_modify_speed:
 811
 812                        rc = fdt_setprop(blob, nodeoff, "maximum-speed", speed, strlen(speed) + 1);
 813                        if (rc) {
 814                                if (rc == -FDT_ERR_NOSPACE) {
 815                                        rc = fdt_increase_size(blob, 512);
 816                                        if (!rc)
 817                                                goto usb_modify_speed;
 818                                }
 819                                printf("Unable to set property %s:%s, err=%s\n",
 820                                       usb_dwc3_path[v], "maximum-speed", fdt_strerror(rc));
 821                        } else {
 822                                printf("Modify %s:%s = %s\n",
 823                                       usb_dwc3_path[v], "maximum-speed", speed);
 824                        }
 825                } else {
 826                        printf("Can't found %s node\n", usb_dwc3_path[v]);
 827                }
 828        }
 829
 830        /* Disable the CPU idle for A0 chip since the HW does not support it */
 831        if (is_soc_rev(CHIP_REV_1_0)) {
 832                static const char * const nodes_path[] = {
 833                        "/cpus/cpu@0",
 834                        "/cpus/cpu@1",
 835                        "/cpus/cpu@2",
 836                        "/cpus/cpu@3",
 837                };
 838
 839                for (i = 0; i < ARRAY_SIZE(nodes_path); i++) {
 840                        nodeoff = fdt_path_offset(blob, nodes_path[i]);
 841                        if (nodeoff < 0)
 842                                continue; /* Not found, skip it */
 843
 844                        debug("Found %s node\n", nodes_path[i]);
 845
 846                        rc = fdt_delprop(blob, nodeoff, "cpu-idle-states");
 847                        if (rc == -FDT_ERR_NOTFOUND)
 848                                continue;
 849                        if (rc) {
 850                                printf("Unable to update property %s:%s, err=%s\n",
 851                                       nodes_path[i], "status", fdt_strerror(rc));
 852                                return rc;
 853                        }
 854
 855                        debug("Remove %s:%s\n", nodes_path[i],
 856                               "cpu-idle-states");
 857                }
 858        }
 859
 860        if (is_imx8mql()) {
 861                disable_vpu_nodes(blob);
 862                if (check_dcss_fused()) {
 863                        printf("DCSS is fused\n");
 864                        disable_dcss_nodes(blob);
 865                        check_mipi_dsi_nodes(blob);
 866                }
 867        }
 868
 869        if (is_imx8md())
 870                disable_cpu_nodes(blob, 2);
 871
 872#elif defined(CONFIG_IMX8MM)
 873        if (is_imx8mml() || is_imx8mmdl() ||  is_imx8mmsl())
 874                disable_vpu_nodes(blob);
 875
 876        if (is_imx8mmd() || is_imx8mmdl())
 877                disable_cpu_nodes(blob, 2);
 878        else if (is_imx8mms() || is_imx8mmsl())
 879                disable_cpu_nodes(blob, 3);
 880
 881#elif defined(CONFIG_IMX8MN)
 882        if (is_imx8mnl() || is_imx8mndl() ||  is_imx8mnsl())
 883                disable_gpu_nodes(blob);
 884
 885        if (is_imx8mnd() || is_imx8mndl())
 886                disable_cpu_nodes(blob, 2);
 887        else if (is_imx8mns() || is_imx8mnsl())
 888                disable_cpu_nodes(blob, 3);
 889
 890#elif defined(CONFIG_IMX8MP)
 891        if (is_imx8mpl())
 892                disable_vpu_nodes(blob);
 893
 894        if (is_imx8mpl() || is_imx8mp6())
 895                disable_npu_nodes(blob);
 896
 897        if (is_imx8mpl())
 898                disable_isp_nodes(blob);
 899
 900        if (is_imx8mpl() || is_imx8mp6())
 901                disable_dsp_nodes(blob);
 902
 903        if (is_imx8mpd())
 904                disable_cpu_nodes(blob, 2);
 905#endif
 906
 907        return 0;
 908}
 909#endif
 910
 911#if !CONFIG_IS_ENABLED(SYSRESET)
 912void reset_cpu(ulong addr)
 913{
 914        struct watchdog_regs *wdog = (struct watchdog_regs *)WDOG1_BASE_ADDR;
 915
 916        /* Clear WDA to trigger WDOG_B immediately */
 917        writew((SET_WCR_WT(1) | WCR_WDT | WCR_WDE | WCR_SRS), &wdog->wcr);
 918
 919        while (1) {
 920                /*
 921                 * spin for .5 seconds before reset
 922                 */
 923        }
 924}
 925#endif
 926
 927#if defined(CONFIG_ARCH_MISC_INIT)
 928static void acquire_buildinfo(void)
 929{
 930        u64 atf_commit = 0;
 931        struct arm_smccc_res res;
 932
 933        /* Get ARM Trusted Firmware commit id */
 934        arm_smccc_smc(IMX_SIP_BUILDINFO, IMX_SIP_BUILDINFO_GET_COMMITHASH,
 935                      0, 0, 0, 0, 0, 0, &res);
 936        atf_commit = res.a0;
 937        if (atf_commit == 0xffffffff) {
 938                debug("ATF does not support build info\n");
 939                atf_commit = 0x30; /* Display 0, 0 ascii is 0x30 */
 940        }
 941
 942        printf("\n BuildInfo:\n  - ATF %s\n\n", (char *)&atf_commit);
 943}
 944
 945int arch_misc_init(void)
 946{
 947        acquire_buildinfo();
 948
 949        return 0;
 950}
 951#endif
 952
 953void imx_tmu_arch_init(void *reg_base)
 954{
 955        if (is_imx8mm() || is_imx8mn()) {
 956                /* Load TCALIV and TASR from fuses */
 957                struct ocotp_regs *ocotp =
 958                        (struct ocotp_regs *)OCOTP_BASE_ADDR;
 959                struct fuse_bank *bank = &ocotp->bank[3];
 960                struct fuse_bank3_regs *fuse =
 961                        (struct fuse_bank3_regs *)bank->fuse_regs;
 962
 963                u32 tca_rt, tca_hr, tca_en;
 964                u32 buf_vref, buf_slope;
 965
 966                tca_rt = fuse->ana0 & 0xFF;
 967                tca_hr = (fuse->ana0 & 0xFF00) >> 8;
 968                tca_en = (fuse->ana0 & 0x2000000) >> 25;
 969
 970                buf_vref = (fuse->ana0 & 0x1F00000) >> 20;
 971                buf_slope = (fuse->ana0 & 0xF0000) >> 16;
 972
 973                writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
 974                writel((tca_en << 31) | (tca_hr << 16) | tca_rt,
 975                       (ulong)reg_base + 0x30);
 976        }
 977#ifdef CONFIG_IMX8MP
 978        /* Load TCALIV0/1/m40 and TRIM from fuses */
 979        struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
 980        struct fuse_bank *bank = &ocotp->bank[38];
 981        struct fuse_bank38_regs *fuse =
 982                (struct fuse_bank38_regs *)bank->fuse_regs;
 983        struct fuse_bank *bank2 = &ocotp->bank[39];
 984        struct fuse_bank39_regs *fuse2 =
 985                (struct fuse_bank39_regs *)bank2->fuse_regs;
 986        u32 buf_vref, buf_slope, bjt_cur, vlsb, bgr;
 987        u32 reg;
 988        u32 tca40[2], tca25[2], tca105[2];
 989
 990        /* For blank sample */
 991        if (!fuse->ana_trim2 && !fuse->ana_trim3 &&
 992            !fuse->ana_trim4 && !fuse2->ana_trim5) {
 993                /* Use a default 25C binary codes */
 994                tca25[0] = 1596;
 995                tca25[1] = 1596;
 996                writel(tca25[0], (ulong)reg_base + 0x30);
 997                writel(tca25[1], (ulong)reg_base + 0x34);
 998                return;
 999        }
1000
1001        buf_vref = (fuse->ana_trim2 & 0xc0) >> 6;
1002        buf_slope = (fuse->ana_trim2 & 0xF00) >> 8;
1003        bjt_cur = (fuse->ana_trim2 & 0xF000) >> 12;
1004        bgr = (fuse->ana_trim2 & 0xF0000) >> 16;
1005        vlsb = (fuse->ana_trim2 & 0xF00000) >> 20;
1006        writel(buf_vref | (buf_slope << 16), (ulong)reg_base + 0x28);
1007
1008        reg = (bgr << 28) | (bjt_cur << 20) | (vlsb << 12) | (1 << 7);
1009        writel(reg, (ulong)reg_base + 0x3c);
1010
1011        tca40[0] = (fuse->ana_trim3 & 0xFFF0000) >> 16;
1012        tca25[0] = (fuse->ana_trim3 & 0xF0000000) >> 28;
1013        tca25[0] |= ((fuse->ana_trim4 & 0xFF) << 4);
1014        tca105[0] = (fuse->ana_trim4 & 0xFFF00) >> 8;
1015        tca40[1] = (fuse->ana_trim4 & 0xFFF00000) >> 20;
1016        tca25[1] = fuse2->ana_trim5 & 0xFFF;
1017        tca105[1] = (fuse2->ana_trim5 & 0xFFF000) >> 12;
1018
1019        /* use 25c for 1p calibration */
1020        writel(tca25[0] | (tca105[0] << 16), (ulong)reg_base + 0x30);
1021        writel(tca25[1] | (tca105[1] << 16), (ulong)reg_base + 0x34);
1022        writel(tca40[0] | (tca40[1] << 16), (ulong)reg_base + 0x38);
1023#endif
1024}
1025
1026#if defined(CONFIG_SPL_BUILD)
1027#if defined(CONFIG_IMX8MQ) || defined(CONFIG_IMX8MM) || defined(CONFIG_IMX8MN)
1028bool serror_need_skip = true;
1029
1030void do_error(struct pt_regs *pt_regs, unsigned int esr)
1031{
1032        /*
1033         * If stack is still in ROM reserved OCRAM not switch to SPL,
1034         * it is the ROM SError
1035         */
1036        ulong sp;
1037
1038        asm volatile("mov %0, sp" : "=r"(sp) : );
1039
1040        if (serror_need_skip && sp < 0x910000 && sp >= 0x900000) {
1041                /* Check for ERR050342, imx8mq HDCP enabled parts */
1042                if (is_imx8mq() && !(readl(OCOTP_BASE_ADDR + 0x450) & 0x08000000)) {
1043                        serror_need_skip = false;
1044                        return; /* Do nothing skip the SError in ROM */
1045                }
1046
1047                /* Check for ERR050350, field return mode for imx8mq, mm and mn */
1048                if (readl(OCOTP_BASE_ADDR + 0x630) & 0x1) {
1049                        serror_need_skip = false;
1050                        return; /* Do nothing skip the SError in ROM */
1051                }
1052        }
1053
1054        efi_restore_gd();
1055        printf("\"Error\" handler, esr 0x%08x\n", esr);
1056        show_regs(pt_regs);
1057        panic("Resetting CPU ...\n");
1058}
1059#endif
1060#endif
1061
1062#if defined(CONFIG_IMX8MN) || defined(CONFIG_IMX8MP)
1063enum env_location env_get_location(enum env_operation op, int prio)
1064{
1065        enum boot_device dev = get_boot_device();
1066        enum env_location env_loc = ENVL_UNKNOWN;
1067
1068        if (prio)
1069                return env_loc;
1070
1071        switch (dev) {
1072#ifdef CONFIG_ENV_IS_IN_SPI_FLASH
1073        case QSPI_BOOT:
1074                env_loc = ENVL_SPI_FLASH;
1075                break;
1076#endif
1077#ifdef CONFIG_ENV_IS_IN_NAND
1078        case NAND_BOOT:
1079                env_loc = ENVL_NAND;
1080                break;
1081#endif
1082#ifdef CONFIG_ENV_IS_IN_MMC
1083        case SD1_BOOT:
1084        case SD2_BOOT:
1085        case SD3_BOOT:
1086        case MMC1_BOOT:
1087        case MMC2_BOOT:
1088        case MMC3_BOOT:
1089                env_loc =  ENVL_MMC;
1090                break;
1091#endif
1092        default:
1093#if defined(CONFIG_ENV_IS_NOWHERE)
1094                env_loc = ENVL_NOWHERE;
1095#endif
1096                break;
1097        }
1098
1099        return env_loc;
1100}
1101
1102#ifndef ENV_IS_EMBEDDED
1103long long env_get_offset(long long defautl_offset)
1104{
1105        enum boot_device dev = get_boot_device();
1106
1107        switch (dev) {
1108        case NAND_BOOT:
1109                return (60 << 20);  /* 60MB offset for NAND */
1110        default:
1111                break;
1112        }
1113
1114        return defautl_offset;
1115}
1116#endif
1117#endif
1118