uboot/board/xilinx/zynqmp/zynqmp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2014 - 2015 Xilinx, Inc.
   4 * Michal Simek <michal.simek@xilinx.com>
   5 */
   6
   7#include <common.h>
   8#include <sata.h>
   9#include <ahci.h>
  10#include <scsi.h>
  11#include <malloc.h>
  12#include <wdt.h>
  13#include <asm/arch/clk.h>
  14#include <asm/arch/hardware.h>
  15#include <asm/arch/sys_proto.h>
  16#include <asm/arch/psu_init_gpl.h>
  17#include <asm/io.h>
  18#include <dm/device.h>
  19#include <dm/uclass.h>
  20#include <usb.h>
  21#include <dwc3-uboot.h>
  22#include <zynqmppl.h>
  23#include <i2c.h>
  24#include <g_dnl.h>
  25
  26DECLARE_GLOBAL_DATA_PTR;
  27
  28#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
  29static struct udevice *watchdog_dev;
  30#endif
  31
  32#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
  33    !defined(CONFIG_SPL_BUILD)
  34static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
  35
  36static const struct {
  37        u32 id;
  38        u32 ver;
  39        char *name;
  40        bool evexists;
  41} zynqmp_devices[] = {
  42        {
  43                .id = 0x10,
  44                .name = "3eg",
  45        },
  46        {
  47                .id = 0x10,
  48                .ver = 0x2c,
  49                .name = "3cg",
  50        },
  51        {
  52                .id = 0x11,
  53                .name = "2eg",
  54        },
  55        {
  56                .id = 0x11,
  57                .ver = 0x2c,
  58                .name = "2cg",
  59        },
  60        {
  61                .id = 0x20,
  62                .name = "5ev",
  63                .evexists = 1,
  64        },
  65        {
  66                .id = 0x20,
  67                .ver = 0x100,
  68                .name = "5eg",
  69                .evexists = 1,
  70        },
  71        {
  72                .id = 0x20,
  73                .ver = 0x12c,
  74                .name = "5cg",
  75        },
  76        {
  77                .id = 0x21,
  78                .name = "4ev",
  79                .evexists = 1,
  80        },
  81        {
  82                .id = 0x21,
  83                .ver = 0x100,
  84                .name = "4eg",
  85                .evexists = 1,
  86        },
  87        {
  88                .id = 0x21,
  89                .ver = 0x12c,
  90                .name = "4cg",
  91        },
  92        {
  93                .id = 0x30,
  94                .name = "7ev",
  95                .evexists = 1,
  96        },
  97        {
  98                .id = 0x30,
  99                .ver = 0x100,
 100                .name = "7eg",
 101                .evexists = 1,
 102        },
 103        {
 104                .id = 0x30,
 105                .ver = 0x12c,
 106                .name = "7cg",
 107        },
 108        {
 109                .id = 0x38,
 110                .name = "9eg",
 111        },
 112        {
 113                .id = 0x38,
 114                .ver = 0x2c,
 115                .name = "9cg",
 116        },
 117        {
 118                .id = 0x39,
 119                .name = "6eg",
 120        },
 121        {
 122                .id = 0x39,
 123                .ver = 0x2c,
 124                .name = "6cg",
 125        },
 126        {
 127                .id = 0x40,
 128                .name = "11eg",
 129        },
 130        { /* For testing purpose only */
 131                .id = 0x50,
 132                .ver = 0x2c,
 133                .name = "15cg",
 134        },
 135        {
 136                .id = 0x50,
 137                .name = "15eg",
 138        },
 139        {
 140                .id = 0x58,
 141                .name = "19eg",
 142        },
 143        {
 144                .id = 0x59,
 145                .name = "17eg",
 146        },
 147        {
 148                .id = 0x61,
 149                .name = "21dr",
 150        },
 151        {
 152                .id = 0x63,
 153                .name = "23dr",
 154        },
 155        {
 156                .id = 0x65,
 157                .name = "25dr",
 158        },
 159        {
 160                .id = 0x64,
 161                .name = "27dr",
 162        },
 163        {
 164                .id = 0x60,
 165                .name = "28dr",
 166        },
 167        {
 168                .id = 0x62,
 169                .name = "29dr",
 170        },
 171};
 172#endif
 173
 174int chip_id(unsigned char id)
 175{
 176        struct pt_regs regs;
 177        int val = -EINVAL;
 178
 179        if (current_el() != 3) {
 180                regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
 181                regs.regs[1] = 0;
 182                regs.regs[2] = 0;
 183                regs.regs[3] = 0;
 184
 185                smc_call(&regs);
 186
 187                /*
 188                 * SMC returns:
 189                 * regs[0][31:0]  = status of the operation
 190                 * regs[0][63:32] = CSU.IDCODE register
 191                 * regs[1][31:0]  = CSU.version register
 192                 * regs[1][63:32] = CSU.IDCODE2 register
 193                 */
 194                switch (id) {
 195                case IDCODE:
 196                        regs.regs[0] = upper_32_bits(regs.regs[0]);
 197                        regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
 198                                        ZYNQMP_CSU_IDCODE_SVD_MASK;
 199                        regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
 200                        val = regs.regs[0];
 201                        break;
 202                case VERSION:
 203                        regs.regs[1] = lower_32_bits(regs.regs[1]);
 204                        regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK;
 205                        val = regs.regs[1];
 206                        break;
 207                case IDCODE2:
 208                        regs.regs[1] = lower_32_bits(regs.regs[1]);
 209                        regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
 210                        val = regs.regs[1];
 211                        break;
 212                default:
 213                        printf("%s, Invalid Req:0x%x\n", __func__, id);
 214                }
 215        } else {
 216                switch (id) {
 217                case IDCODE:
 218                        val = readl(ZYNQMP_CSU_IDCODE_ADDR);
 219                        val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
 220                               ZYNQMP_CSU_IDCODE_SVD_MASK;
 221                        val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
 222                        break;
 223                case VERSION:
 224                        val = readl(ZYNQMP_CSU_VER_ADDR);
 225                        val &= ZYNQMP_CSU_SILICON_VER_MASK;
 226                        break;
 227                default:
 228                        printf("%s, Invalid Req:0x%x\n", __func__, id);
 229                }
 230        }
 231
 232        return val;
 233}
 234
 235#define ZYNQMP_VERSION_SIZE             9
 236#define ZYNQMP_PL_STATUS_BIT            9
 237#define ZYNQMP_PL_STATUS_MASK           BIT(ZYNQMP_PL_STATUS_BIT)
 238#define ZYNQMP_CSU_VERSION_MASK         ~(ZYNQMP_PL_STATUS_MASK)
 239
 240#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
 241        !defined(CONFIG_SPL_BUILD)
 242static char *zynqmp_get_silicon_idcode_name(void)
 243{
 244        u32 i, id, ver;
 245        char *buf;
 246        static char name[ZYNQMP_VERSION_SIZE];
 247
 248        id = chip_id(IDCODE);
 249        ver = chip_id(IDCODE2);
 250
 251        for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
 252                if ((zynqmp_devices[i].id == id) &&
 253                    (zynqmp_devices[i].ver == (ver &
 254                    ZYNQMP_CSU_VERSION_MASK))) {
 255                        strncat(name, "zu", 2);
 256                        strncat(name, zynqmp_devices[i].name,
 257                                ZYNQMP_VERSION_SIZE - 3);
 258                        break;
 259                }
 260        }
 261
 262        if (i >= ARRAY_SIZE(zynqmp_devices))
 263                return "unknown";
 264
 265        if (!zynqmp_devices[i].evexists)
 266                return name;
 267
 268        if (ver & ZYNQMP_PL_STATUS_MASK)
 269                return name;
 270
 271        if (strstr(name, "eg") || strstr(name, "ev")) {
 272                buf = strstr(name, "e");
 273                *buf = '\0';
 274        }
 275
 276        return name;
 277}
 278#endif
 279
 280int board_early_init_f(void)
 281{
 282        int ret = 0;
 283#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP)
 284        zynqmp_pmufw_version();
 285#endif
 286
 287#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
 288        ret = psu_init();
 289#endif
 290
 291#if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD)
 292        /* bss is not cleared at time when watchdog_reset() is called */
 293        watchdog_dev = NULL;
 294#endif
 295
 296        return ret;
 297}
 298
 299int board_init(void)
 300{
 301        printf("EL Level:\tEL%d\n", current_el());
 302
 303#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
 304    !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
 305    defined(CONFIG_SPL_BUILD))
 306        if (current_el() != 3) {
 307                zynqmppl.name = zynqmp_get_silicon_idcode_name();
 308                printf("Chip ID:\t%s\n", zynqmppl.name);
 309                fpga_init();
 310                fpga_add(fpga_xilinx, &zynqmppl);
 311        }
 312#endif
 313
 314#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT)
 315        if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) {
 316                debug("Watchdog: Not found by seq!\n");
 317                if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
 318                        puts("Watchdog: Not found!\n");
 319                        return 0;
 320                }
 321        }
 322
 323        wdt_start(watchdog_dev, 0, 0);
 324        puts("Watchdog: Started\n");
 325#endif
 326
 327        return 0;
 328}
 329
 330#ifdef CONFIG_WATCHDOG
 331/* Called by macro WATCHDOG_RESET */
 332void watchdog_reset(void)
 333{
 334# if !defined(CONFIG_SPL_BUILD)
 335        static ulong next_reset;
 336        ulong now;
 337
 338        if (!watchdog_dev)
 339                return;
 340
 341        now = timer_get_us();
 342
 343        /* Do not reset the watchdog too often */
 344        if (now > next_reset) {
 345                wdt_reset(watchdog_dev);
 346                next_reset = now + 1000;
 347        }
 348# endif
 349}
 350#endif
 351
 352int board_early_init_r(void)
 353{
 354        u32 val;
 355
 356        if (current_el() != 3)
 357                return 0;
 358
 359        val = readl(&crlapb_base->timestamp_ref_ctrl);
 360        val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
 361
 362        if (!val) {
 363                val = readl(&crlapb_base->timestamp_ref_ctrl);
 364                val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
 365                writel(val, &crlapb_base->timestamp_ref_ctrl);
 366
 367                /* Program freq register in System counter */
 368                writel(zynqmp_get_system_timer_freq(),
 369                       &iou_scntr_secure->base_frequency_id_register);
 370                /* And enable system counter */
 371                writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
 372                       &iou_scntr_secure->counter_control_register);
 373        }
 374        return 0;
 375}
 376
 377int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
 378{
 379#if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \
 380    defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \
 381    defined(CONFIG_ZYNQ_EEPROM_BUS)
 382        i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS);
 383
 384        if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR,
 385                        CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET,
 386                        ethaddr, 6))
 387                printf("I2C EEPROM MAC address read failed\n");
 388#endif
 389
 390        return 0;
 391}
 392
 393unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
 394                         char * const argv[])
 395{
 396        int ret = 0;
 397
 398        if (current_el() > 1) {
 399                smp_kick_all_cpus();
 400                dcache_disable();
 401                armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
 402                                    ES_TO_AARCH64);
 403        } else {
 404                printf("FAIL: current EL is not above EL1\n");
 405                ret = EINVAL;
 406        }
 407        return ret;
 408}
 409
 410#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
 411int dram_init_banksize(void)
 412{
 413        int ret;
 414
 415        ret = fdtdec_setup_memory_banksize();
 416        if (ret)
 417                return ret;
 418
 419        mem_map_fill();
 420
 421        return 0;
 422}
 423
 424int dram_init(void)
 425{
 426        if (fdtdec_setup_mem_size_base() != 0)
 427                return -EINVAL;
 428
 429        return 0;
 430}
 431#else
 432int dram_init_banksize(void)
 433{
 434#if defined(CONFIG_NR_DRAM_BANKS)
 435        gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE;
 436        gd->bd->bi_dram[0].size = get_effective_memsize();
 437#endif
 438
 439        mem_map_fill();
 440
 441        return 0;
 442}
 443
 444int dram_init(void)
 445{
 446        gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE,
 447                                    CONFIG_SYS_SDRAM_SIZE);
 448
 449        return 0;
 450}
 451#endif
 452
 453void reset_cpu(ulong addr)
 454{
 455}
 456
 457static const struct {
 458        u32 bit;
 459        const char *name;
 460} reset_reasons[] = {
 461        { RESET_REASON_DEBUG_SYS, "DEBUG" },
 462        { RESET_REASON_SOFT, "SOFT" },
 463        { RESET_REASON_SRST, "SRST" },
 464        { RESET_REASON_PSONLY, "PS-ONLY" },
 465        { RESET_REASON_PMU, "PMU" },
 466        { RESET_REASON_INTERNAL, "INTERNAL" },
 467        { RESET_REASON_EXTERNAL, "EXTERNAL" },
 468        {}
 469};
 470
 471static u32 reset_reason(void)
 472{
 473        u32 ret;
 474        int i;
 475        const char *reason = NULL;
 476
 477        ret = readl(&crlapb_base->reset_reason);
 478
 479        puts("Reset reason:\t");
 480
 481        for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) {
 482                if (ret & reset_reasons[i].bit) {
 483                        reason = reset_reasons[i].name;
 484                        printf("%s ", reset_reasons[i].name);
 485                        break;
 486                }
 487        }
 488
 489        puts("\n");
 490
 491        env_set("reset_reason", reason);
 492
 493        writel(~0, &crlapb_base->reset_reason);
 494
 495        return ret;
 496}
 497
 498int board_late_init(void)
 499{
 500        u32 reg = 0;
 501        u8 bootmode;
 502        struct udevice *dev;
 503        int bootseq = -1;
 504        int bootseq_len = 0;
 505        int env_targets_len = 0;
 506        const char *mode;
 507        char *new_targets;
 508        char *env_targets;
 509        int ret;
 510
 511        if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
 512                debug("Saved variables - Skipping\n");
 513                return 0;
 514        }
 515
 516        ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, &reg);
 517        if (ret)
 518                return -EINVAL;
 519
 520        if (reg >> BOOT_MODE_ALT_SHIFT)
 521                reg >>= BOOT_MODE_ALT_SHIFT;
 522
 523        bootmode = reg & BOOT_MODES_MASK;
 524
 525        puts("Bootmode: ");
 526        switch (bootmode) {
 527        case USB_MODE:
 528                puts("USB_MODE\n");
 529                mode = "usb";
 530                env_set("modeboot", "usb_dfu_spl");
 531                break;
 532        case JTAG_MODE:
 533                puts("JTAG_MODE\n");
 534                mode = "pxe dhcp";
 535                env_set("modeboot", "jtagboot");
 536                break;
 537        case QSPI_MODE_24BIT:
 538        case QSPI_MODE_32BIT:
 539                mode = "qspi0";
 540                puts("QSPI_MODE\n");
 541                env_set("modeboot", "qspiboot");
 542                break;
 543        case EMMC_MODE:
 544                puts("EMMC_MODE\n");
 545                mode = "mmc0";
 546                env_set("modeboot", "emmcboot");
 547                break;
 548        case SD_MODE:
 549                puts("SD_MODE\n");
 550                if (uclass_get_device_by_name(UCLASS_MMC,
 551                                              "sdhci@ff160000", &dev)) {
 552                        puts("Boot from SD0 but without SD0 enabled!\n");
 553                        return -1;
 554                }
 555                debug("mmc0 device found at %p, seq %d\n", dev, dev->seq);
 556
 557                mode = "mmc";
 558                bootseq = dev->seq;
 559                env_set("modeboot", "sdboot");
 560                break;
 561        case SD1_LSHFT_MODE:
 562                puts("LVL_SHFT_");
 563                /* fall through */
 564        case SD_MODE1:
 565                puts("SD_MODE1\n");
 566                if (uclass_get_device_by_name(UCLASS_MMC,
 567                                              "sdhci@ff170000", &dev)) {
 568                        puts("Boot from SD1 but without SD1 enabled!\n");
 569                        return -1;
 570                }
 571                debug("mmc1 device found at %p, seq %d\n", dev, dev->seq);
 572
 573                mode = "mmc";
 574                bootseq = dev->seq;
 575                env_set("modeboot", "sdboot");
 576                break;
 577        case NAND_MODE:
 578                puts("NAND_MODE\n");
 579                mode = "nand0";
 580                env_set("modeboot", "nandboot");
 581                break;
 582        default:
 583                mode = "";
 584                printf("Invalid Boot Mode:0x%x\n", bootmode);
 585                break;
 586        }
 587
 588        if (bootseq >= 0) {
 589                bootseq_len = snprintf(NULL, 0, "%i", bootseq);
 590                debug("Bootseq len: %x\n", bootseq_len);
 591        }
 592
 593        /*
 594         * One terminating char + one byte for space between mode
 595         * and default boot_targets
 596         */
 597        env_targets = env_get("boot_targets");
 598        if (env_targets)
 599                env_targets_len = strlen(env_targets);
 600
 601        new_targets = calloc(1, strlen(mode) + env_targets_len + 2 +
 602                             bootseq_len);
 603        if (!new_targets)
 604                return -ENOMEM;
 605
 606        if (bootseq >= 0)
 607                sprintf(new_targets, "%s%x %s", mode, bootseq,
 608                        env_targets ? env_targets : "");
 609        else
 610                sprintf(new_targets, "%s %s", mode,
 611                        env_targets ? env_targets : "");
 612
 613        env_set("boot_targets", new_targets);
 614
 615        reset_reason();
 616
 617        return 0;
 618}
 619
 620int checkboard(void)
 621{
 622        puts("Board: Xilinx ZynqMP\n");
 623        return 0;
 624}
 625