uboot/board/xilinx/zynqmp/zynqmp.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2014 - 2015 Xilinx, Inc.
   3 * Michal Simek <michal.simek@xilinx.com>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <sata.h>
  10#include <ahci.h>
  11#include <scsi.h>
  12#include <malloc.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 <usb.h>
  19#include <dwc3-uboot.h>
  20#include <zynqmppl.h>
  21#include <i2c.h>
  22#include <g_dnl.h>
  23
  24DECLARE_GLOBAL_DATA_PTR;
  25
  26#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
  27    !defined(CONFIG_SPL_BUILD)
  28static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC;
  29
  30static const struct {
  31        u32 id;
  32        u32 ver;
  33        char *name;
  34} zynqmp_devices[] = {
  35        {
  36                .id = 0x10,
  37                .name = "3eg",
  38        },
  39        {
  40                .id = 0x10,
  41                .ver = 0x2c,
  42                .name = "3cg",
  43        },
  44        {
  45                .id = 0x11,
  46                .name = "2eg",
  47        },
  48        {
  49                .id = 0x11,
  50                .ver = 0x2c,
  51                .name = "2cg",
  52        },
  53        {
  54                .id = 0x20,
  55                .name = "5ev",
  56        },
  57        {
  58                .id = 0x20,
  59                .ver = 0x100,
  60                .name = "5eg",
  61        },
  62        {
  63                .id = 0x20,
  64                .ver = 0x12c,
  65                .name = "5cg",
  66        },
  67        {
  68                .id = 0x21,
  69                .name = "4ev",
  70        },
  71        {
  72                .id = 0x21,
  73                .ver = 0x100,
  74                .name = "4eg",
  75        },
  76        {
  77                .id = 0x21,
  78                .ver = 0x12c,
  79                .name = "4cg",
  80        },
  81        {
  82                .id = 0x30,
  83                .name = "7ev",
  84        },
  85        {
  86                .id = 0x30,
  87                .ver = 0x100,
  88                .name = "7eg",
  89        },
  90        {
  91                .id = 0x30,
  92                .ver = 0x12c,
  93                .name = "7cg",
  94        },
  95        {
  96                .id = 0x38,
  97                .name = "9eg",
  98        },
  99        {
 100                .id = 0x38,
 101                .ver = 0x2c,
 102                .name = "9cg",
 103        },
 104        {
 105                .id = 0x39,
 106                .name = "6eg",
 107        },
 108        {
 109                .id = 0x39,
 110                .ver = 0x2c,
 111                .name = "6cg",
 112        },
 113        {
 114                .id = 0x40,
 115                .name = "11eg",
 116        },
 117        { /* For testing purpose only */
 118                .id = 0x50,
 119                .ver = 0x2c,
 120                .name = "15cg",
 121        },
 122        {
 123                .id = 0x50,
 124                .name = "15eg",
 125        },
 126        {
 127                .id = 0x58,
 128                .name = "19eg",
 129        },
 130        {
 131                .id = 0x59,
 132                .name = "17eg",
 133        },
 134        {
 135                .id = 0x61,
 136                .name = "21dr",
 137        },
 138        {
 139                .id = 0x63,
 140                .name = "23dr",
 141        },
 142        {
 143                .id = 0x65,
 144                .name = "25dr",
 145        },
 146        {
 147                .id = 0x64,
 148                .name = "27dr",
 149        },
 150        {
 151                .id = 0x60,
 152                .name = "28dr",
 153        },
 154        {
 155                .id = 0x62,
 156                .name = "29dr",
 157        },
 158};
 159#endif
 160
 161int chip_id(unsigned char id)
 162{
 163        struct pt_regs regs;
 164        int val = -EINVAL;
 165
 166        if (current_el() != 3) {
 167                regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID;
 168                regs.regs[1] = 0;
 169                regs.regs[2] = 0;
 170                regs.regs[3] = 0;
 171
 172                smc_call(&regs);
 173
 174                /*
 175                 * SMC returns:
 176                 * regs[0][31:0]  = status of the operation
 177                 * regs[0][63:32] = CSU.IDCODE register
 178                 * regs[1][31:0]  = CSU.version register
 179                 * regs[1][63:32] = CSU.IDCODE2 register
 180                 */
 181                switch (id) {
 182                case IDCODE:
 183                        regs.regs[0] = upper_32_bits(regs.regs[0]);
 184                        regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
 185                                        ZYNQMP_CSU_IDCODE_SVD_MASK;
 186                        regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
 187                        val = regs.regs[0];
 188                        break;
 189                case VERSION:
 190                        regs.regs[1] = lower_32_bits(regs.regs[1]);
 191                        regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK;
 192                        val = regs.regs[1];
 193                        break;
 194                case IDCODE2:
 195                        regs.regs[1] = lower_32_bits(regs.regs[1]);
 196                        regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT;
 197                        val = regs.regs[1];
 198                        break;
 199                default:
 200                        printf("%s, Invalid Req:0x%x\n", __func__, id);
 201                }
 202        } else {
 203                switch (id) {
 204                case IDCODE:
 205                        val = readl(ZYNQMP_CSU_IDCODE_ADDR);
 206                        val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK |
 207                               ZYNQMP_CSU_IDCODE_SVD_MASK;
 208                        val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT;
 209                        break;
 210                case VERSION:
 211                        val = readl(ZYNQMP_CSU_VER_ADDR);
 212                        val &= ZYNQMP_CSU_SILICON_VER_MASK;
 213                        break;
 214                default:
 215                        printf("%s, Invalid Req:0x%x\n", __func__, id);
 216                }
 217        }
 218
 219        return val;
 220}
 221
 222#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
 223        !defined(CONFIG_SPL_BUILD)
 224static char *zynqmp_get_silicon_idcode_name(void)
 225{
 226        u32 i, id, ver;
 227
 228        id = chip_id(IDCODE);
 229        ver = chip_id(IDCODE2);
 230
 231        for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) {
 232                if (zynqmp_devices[i].id == id && zynqmp_devices[i].ver == ver)
 233                        return zynqmp_devices[i].name;
 234        }
 235        return "unknown";
 236}
 237#endif
 238
 239int board_early_init_f(void)
 240{
 241        int ret = 0;
 242#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP)
 243        zynqmp_pmufw_version();
 244#endif
 245
 246#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED)
 247        ret = psu_init();
 248#endif
 249
 250        return ret;
 251}
 252
 253#define ZYNQMP_VERSION_SIZE     9
 254
 255int board_init(void)
 256{
 257        printf("EL Level:\tEL%d\n", current_el());
 258
 259#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \
 260    !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \
 261    defined(CONFIG_SPL_BUILD))
 262        if (current_el() != 3) {
 263                static char version[ZYNQMP_VERSION_SIZE];
 264
 265                strncat(version, "zu", 2);
 266                zynqmppl.name = strncat(version,
 267                                        zynqmp_get_silicon_idcode_name(),
 268                                        ZYNQMP_VERSION_SIZE - 3);
 269                printf("Chip ID:\t%s\n", zynqmppl.name);
 270                fpga_init();
 271                fpga_add(fpga_xilinx, &zynqmppl);
 272        }
 273#endif
 274
 275        return 0;
 276}
 277
 278int board_early_init_r(void)
 279{
 280        u32 val;
 281
 282        if (current_el() != 3)
 283                return 0;
 284
 285        val = readl(&crlapb_base->timestamp_ref_ctrl);
 286        val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
 287
 288        if (!val) {
 289                val = readl(&crlapb_base->timestamp_ref_ctrl);
 290                val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT;
 291                writel(val, &crlapb_base->timestamp_ref_ctrl);
 292
 293                /* Program freq register in System counter */
 294                writel(zynqmp_get_system_timer_freq(),
 295                       &iou_scntr_secure->base_frequency_id_register);
 296                /* And enable system counter */
 297                writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN,
 298                       &iou_scntr_secure->counter_control_register);
 299        }
 300        return 0;
 301}
 302
 303int zynq_board_read_rom_ethaddr(unsigned char *ethaddr)
 304{
 305#if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \
 306    defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \
 307    defined(CONFIG_ZYNQ_EEPROM_BUS)
 308        i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS);
 309
 310        if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR,
 311                        CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET,
 312                        ethaddr, 6))
 313                printf("I2C EEPROM MAC address read failed\n");
 314#endif
 315
 316        return 0;
 317}
 318
 319#if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE)
 320int dram_init_banksize(void)
 321{
 322        return fdtdec_setup_memory_banksize();
 323}
 324
 325int dram_init(void)
 326{
 327        if (fdtdec_setup_memory_size() != 0)
 328                return -EINVAL;
 329
 330        return 0;
 331}
 332#else
 333int dram_init(void)
 334{
 335        gd->ram_size = CONFIG_SYS_SDRAM_SIZE;
 336
 337        return 0;
 338}
 339#endif
 340
 341void reset_cpu(ulong addr)
 342{
 343}
 344
 345int board_late_init(void)
 346{
 347        u32 reg = 0;
 348        u8 bootmode;
 349        const char *mode;
 350        char *new_targets;
 351        char *env_targets;
 352        int ret;
 353
 354        if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
 355                debug("Saved variables - Skipping\n");
 356                return 0;
 357        }
 358
 359        ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, &reg);
 360        if (ret)
 361                return -EINVAL;
 362
 363        if (reg >> BOOT_MODE_ALT_SHIFT)
 364                reg >>= BOOT_MODE_ALT_SHIFT;
 365
 366        bootmode = reg & BOOT_MODES_MASK;
 367
 368        puts("Bootmode: ");
 369        switch (bootmode) {
 370        case USB_MODE:
 371                puts("USB_MODE\n");
 372                mode = "usb";
 373                env_set("modeboot", "usb_dfu_spl");
 374                break;
 375        case JTAG_MODE:
 376                puts("JTAG_MODE\n");
 377                mode = "pxe dhcp";
 378                env_set("modeboot", "jtagboot");
 379                break;
 380        case QSPI_MODE_24BIT:
 381        case QSPI_MODE_32BIT:
 382                mode = "qspi0";
 383                puts("QSPI_MODE\n");
 384                env_set("modeboot", "qspiboot");
 385                break;
 386        case EMMC_MODE:
 387                puts("EMMC_MODE\n");
 388                mode = "mmc0";
 389                env_set("modeboot", "emmcboot");
 390                break;
 391        case SD_MODE:
 392                puts("SD_MODE\n");
 393                mode = "mmc0";
 394                env_set("modeboot", "sdboot");
 395                break;
 396        case SD1_LSHFT_MODE:
 397                puts("LVL_SHFT_");
 398                /* fall through */
 399        case SD_MODE1:
 400                puts("SD_MODE1\n");
 401#if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1)
 402                mode = "mmc1";
 403                env_set("sdbootdev", "1");
 404#else
 405                mode = "mmc0";
 406#endif
 407                env_set("modeboot", "sdboot");
 408                break;
 409        case NAND_MODE:
 410                puts("NAND_MODE\n");
 411                mode = "nand0";
 412                env_set("modeboot", "nandboot");
 413                break;
 414        default:
 415                mode = "";
 416                printf("Invalid Boot Mode:0x%x\n", bootmode);
 417                break;
 418        }
 419
 420        /*
 421         * One terminating char + one byte for space between mode
 422         * and default boot_targets
 423         */
 424        env_targets = env_get("boot_targets");
 425        if (env_targets) {
 426                new_targets = calloc(1, strlen(mode) +
 427                                     strlen(env_targets) + 2);
 428                sprintf(new_targets, "%s %s", mode, env_targets);
 429        } else {
 430                new_targets = calloc(1, strlen(mode) + 2);
 431                sprintf(new_targets, "%s", mode);
 432        }
 433
 434        env_set("boot_targets", new_targets);
 435
 436        return 0;
 437}
 438
 439int checkboard(void)
 440{
 441        puts("Board: Xilinx ZynqMP\n");
 442        return 0;
 443}
 444
 445#ifdef CONFIG_USB_DWC3
 446static struct dwc3_device dwc3_device_data0 = {
 447        .maximum_speed = USB_SPEED_HIGH,
 448        .base = ZYNQMP_USB0_XHCI_BASEADDR,
 449        .dr_mode = USB_DR_MODE_PERIPHERAL,
 450        .index = 0,
 451};
 452
 453static struct dwc3_device dwc3_device_data1 = {
 454        .maximum_speed = USB_SPEED_HIGH,
 455        .base = ZYNQMP_USB1_XHCI_BASEADDR,
 456        .dr_mode = USB_DR_MODE_PERIPHERAL,
 457        .index = 1,
 458};
 459
 460int usb_gadget_handle_interrupts(int index)
 461{
 462        dwc3_uboot_handle_interrupt(index);
 463        return 0;
 464}
 465
 466int board_usb_init(int index, enum usb_init_type init)
 467{
 468        debug("%s: index %x\n", __func__, index);
 469
 470#if defined(CONFIG_USB_GADGET_DOWNLOAD)
 471        g_dnl_set_serialnumber(CONFIG_SYS_CONFIG_NAME);
 472#endif
 473
 474        switch (index) {
 475        case 0:
 476                return dwc3_uboot_init(&dwc3_device_data0);
 477        case 1:
 478                return dwc3_uboot_init(&dwc3_device_data1);
 479        };
 480
 481        return -1;
 482}
 483
 484int board_usb_cleanup(int index, enum usb_init_type init)
 485{
 486        dwc3_uboot_exit(index);
 487        return 0;
 488}
 489#endif
 490