184c7204bSMichal Simek /* 284c7204bSMichal Simek * (C) Copyright 2014 - 2015 Xilinx, Inc. 384c7204bSMichal Simek * Michal Simek <michal.simek@xilinx.com> 484c7204bSMichal Simek * 584c7204bSMichal Simek * SPDX-License-Identifier: GPL-2.0+ 684c7204bSMichal Simek */ 784c7204bSMichal Simek 884c7204bSMichal Simek #include <common.h> 9679b994aSMichal Simek #include <sata.h> 106fe6f135SMichal Simek #include <ahci.h> 116fe6f135SMichal Simek #include <scsi.h> 12b72894f1SMichal Simek #include <malloc.h> 130785dfd8SMichal Simek #include <asm/arch/clk.h> 1484c7204bSMichal Simek #include <asm/arch/hardware.h> 1584c7204bSMichal Simek #include <asm/arch/sys_proto.h> 162ad341edSMichal Simek #include <asm/arch/psu_init_gpl.h> 1784c7204bSMichal Simek #include <asm/io.h> 1816fa00a7SSiva Durga Prasad Paladugu #include <usb.h> 1916fa00a7SSiva Durga Prasad Paladugu #include <dwc3-uboot.h> 2047e60cbdSMichal Simek #include <zynqmppl.h> 216919b4bfSMichal Simek #include <i2c.h> 229feff385SMichal Simek #include <g_dnl.h> 2384c7204bSMichal Simek 2484c7204bSMichal Simek DECLARE_GLOBAL_DATA_PTR; 2584c7204bSMichal Simek 2647e60cbdSMichal Simek #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 2747e60cbdSMichal Simek !defined(CONFIG_SPL_BUILD) 2847e60cbdSMichal Simek static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC; 2947e60cbdSMichal Simek 3047e60cbdSMichal Simek static const struct { 318ebdf9efSMichal Simek u32 id; 32494fffe7SMichal Simek u32 ver; 3347e60cbdSMichal Simek char *name; 3483bf2ff0SSiva Durga Prasad Paladugu bool evexists; 3547e60cbdSMichal Simek } zynqmp_devices[] = { 3647e60cbdSMichal Simek { 3747e60cbdSMichal Simek .id = 0x10, 3847e60cbdSMichal Simek .name = "3eg", 3947e60cbdSMichal Simek }, 4047e60cbdSMichal Simek { 41494fffe7SMichal Simek .id = 0x10, 42494fffe7SMichal Simek .ver = 0x2c, 43494fffe7SMichal Simek .name = "3cg", 44494fffe7SMichal Simek }, 45494fffe7SMichal Simek { 4647e60cbdSMichal Simek .id = 0x11, 4747e60cbdSMichal Simek .name = "2eg", 4847e60cbdSMichal Simek }, 4947e60cbdSMichal Simek { 50494fffe7SMichal Simek .id = 0x11, 51494fffe7SMichal Simek .ver = 0x2c, 52494fffe7SMichal Simek .name = "2cg", 53494fffe7SMichal Simek }, 54494fffe7SMichal Simek { 5547e60cbdSMichal Simek .id = 0x20, 5647e60cbdSMichal Simek .name = "5ev", 5783bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 5847e60cbdSMichal Simek }, 5947e60cbdSMichal Simek { 60494fffe7SMichal Simek .id = 0x20, 61494fffe7SMichal Simek .ver = 0x100, 62494fffe7SMichal Simek .name = "5eg", 6383bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 64494fffe7SMichal Simek }, 65494fffe7SMichal Simek { 66494fffe7SMichal Simek .id = 0x20, 67494fffe7SMichal Simek .ver = 0x12c, 68494fffe7SMichal Simek .name = "5cg", 69494fffe7SMichal Simek }, 70494fffe7SMichal Simek { 7147e60cbdSMichal Simek .id = 0x21, 7247e60cbdSMichal Simek .name = "4ev", 7383bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 7447e60cbdSMichal Simek }, 7547e60cbdSMichal Simek { 76494fffe7SMichal Simek .id = 0x21, 77494fffe7SMichal Simek .ver = 0x100, 78494fffe7SMichal Simek .name = "4eg", 7983bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 80494fffe7SMichal Simek }, 81494fffe7SMichal Simek { 82494fffe7SMichal Simek .id = 0x21, 83494fffe7SMichal Simek .ver = 0x12c, 84494fffe7SMichal Simek .name = "4cg", 85494fffe7SMichal Simek }, 86494fffe7SMichal Simek { 8747e60cbdSMichal Simek .id = 0x30, 8847e60cbdSMichal Simek .name = "7ev", 8983bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 9047e60cbdSMichal Simek }, 9147e60cbdSMichal Simek { 92494fffe7SMichal Simek .id = 0x30, 93494fffe7SMichal Simek .ver = 0x100, 94494fffe7SMichal Simek .name = "7eg", 9583bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 96494fffe7SMichal Simek }, 97494fffe7SMichal Simek { 98494fffe7SMichal Simek .id = 0x30, 99494fffe7SMichal Simek .ver = 0x12c, 100494fffe7SMichal Simek .name = "7cg", 101494fffe7SMichal Simek }, 102494fffe7SMichal Simek { 10347e60cbdSMichal Simek .id = 0x38, 10447e60cbdSMichal Simek .name = "9eg", 10547e60cbdSMichal Simek }, 10647e60cbdSMichal Simek { 107494fffe7SMichal Simek .id = 0x38, 108494fffe7SMichal Simek .ver = 0x2c, 109494fffe7SMichal Simek .name = "9cg", 110494fffe7SMichal Simek }, 111494fffe7SMichal Simek { 11247e60cbdSMichal Simek .id = 0x39, 11347e60cbdSMichal Simek .name = "6eg", 11447e60cbdSMichal Simek }, 11547e60cbdSMichal Simek { 116494fffe7SMichal Simek .id = 0x39, 117494fffe7SMichal Simek .ver = 0x2c, 118494fffe7SMichal Simek .name = "6cg", 119494fffe7SMichal Simek }, 120494fffe7SMichal Simek { 12147e60cbdSMichal Simek .id = 0x40, 12247e60cbdSMichal Simek .name = "11eg", 12347e60cbdSMichal Simek }, 124494fffe7SMichal Simek { /* For testing purpose only */ 125494fffe7SMichal Simek .id = 0x50, 126494fffe7SMichal Simek .ver = 0x2c, 127494fffe7SMichal Simek .name = "15cg", 128494fffe7SMichal Simek }, 12947e60cbdSMichal Simek { 13047e60cbdSMichal Simek .id = 0x50, 13147e60cbdSMichal Simek .name = "15eg", 13247e60cbdSMichal Simek }, 13347e60cbdSMichal Simek { 13447e60cbdSMichal Simek .id = 0x58, 13547e60cbdSMichal Simek .name = "19eg", 13647e60cbdSMichal Simek }, 13747e60cbdSMichal Simek { 13847e60cbdSMichal Simek .id = 0x59, 13947e60cbdSMichal Simek .name = "17eg", 14047e60cbdSMichal Simek }, 141b030fedfSMichal Simek { 142b030fedfSMichal Simek .id = 0x61, 143b030fedfSMichal Simek .name = "21dr", 144b030fedfSMichal Simek }, 145b030fedfSMichal Simek { 146b030fedfSMichal Simek .id = 0x63, 147b030fedfSMichal Simek .name = "23dr", 148b030fedfSMichal Simek }, 149b030fedfSMichal Simek { 150b030fedfSMichal Simek .id = 0x65, 151b030fedfSMichal Simek .name = "25dr", 152b030fedfSMichal Simek }, 153b030fedfSMichal Simek { 154b030fedfSMichal Simek .id = 0x64, 155b030fedfSMichal Simek .name = "27dr", 156b030fedfSMichal Simek }, 157b030fedfSMichal Simek { 158b030fedfSMichal Simek .id = 0x60, 159b030fedfSMichal Simek .name = "28dr", 160b030fedfSMichal Simek }, 161b030fedfSMichal Simek { 162b030fedfSMichal Simek .id = 0x62, 163b030fedfSMichal Simek .name = "29dr", 164b030fedfSMichal Simek }, 16547e60cbdSMichal Simek }; 16674ba69dbSSiva Durga Prasad Paladugu #endif 16747e60cbdSMichal Simek 168f52bf5a3SSiva Durga Prasad Paladugu int chip_id(unsigned char id) 16947e60cbdSMichal Simek { 17047e60cbdSMichal Simek struct pt_regs regs; 17174ba69dbSSiva Durga Prasad Paladugu int val = -EINVAL; 17274ba69dbSSiva Durga Prasad Paladugu 17374ba69dbSSiva Durga Prasad Paladugu if (current_el() != 3) { 17447e60cbdSMichal Simek regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID; 17547e60cbdSMichal Simek regs.regs[1] = 0; 17647e60cbdSMichal Simek regs.regs[2] = 0; 17747e60cbdSMichal Simek regs.regs[3] = 0; 17847e60cbdSMichal Simek 17947e60cbdSMichal Simek smc_call(®s); 18047e60cbdSMichal Simek 1810cba6abbSSoren Brinkmann /* 1820cba6abbSSoren Brinkmann * SMC returns: 1830cba6abbSSoren Brinkmann * regs[0][31:0] = status of the operation 1840cba6abbSSoren Brinkmann * regs[0][63:32] = CSU.IDCODE register 1850cba6abbSSoren Brinkmann * regs[1][31:0] = CSU.version register 186494fffe7SMichal Simek * regs[1][63:32] = CSU.IDCODE2 register 1870cba6abbSSoren Brinkmann */ 188db3123b4SSiva Durga Prasad Paladugu switch (id) { 189db3123b4SSiva Durga Prasad Paladugu case IDCODE: 1900cba6abbSSoren Brinkmann regs.regs[0] = upper_32_bits(regs.regs[0]); 1910cba6abbSSoren Brinkmann regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 1920cba6abbSSoren Brinkmann ZYNQMP_CSU_IDCODE_SVD_MASK; 1930cba6abbSSoren Brinkmann regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 194db3123b4SSiva Durga Prasad Paladugu val = regs.regs[0]; 195db3123b4SSiva Durga Prasad Paladugu break; 196db3123b4SSiva Durga Prasad Paladugu case VERSION: 197db3123b4SSiva Durga Prasad Paladugu regs.regs[1] = lower_32_bits(regs.regs[1]); 198db3123b4SSiva Durga Prasad Paladugu regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK; 199db3123b4SSiva Durga Prasad Paladugu val = regs.regs[1]; 200db3123b4SSiva Durga Prasad Paladugu break; 201494fffe7SMichal Simek case IDCODE2: 202494fffe7SMichal Simek regs.regs[1] = lower_32_bits(regs.regs[1]); 203494fffe7SMichal Simek regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT; 204494fffe7SMichal Simek val = regs.regs[1]; 205494fffe7SMichal Simek break; 206db3123b4SSiva Durga Prasad Paladugu default: 207db3123b4SSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 208db3123b4SSiva Durga Prasad Paladugu } 20974ba69dbSSiva Durga Prasad Paladugu } else { 21074ba69dbSSiva Durga Prasad Paladugu switch (id) { 21174ba69dbSSiva Durga Prasad Paladugu case IDCODE: 21274ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_IDCODE_ADDR); 21374ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 21474ba69dbSSiva Durga Prasad Paladugu ZYNQMP_CSU_IDCODE_SVD_MASK; 21574ba69dbSSiva Durga Prasad Paladugu val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 21674ba69dbSSiva Durga Prasad Paladugu break; 21774ba69dbSSiva Durga Prasad Paladugu case VERSION: 21874ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_VER_ADDR); 21974ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_SILICON_VER_MASK; 22074ba69dbSSiva Durga Prasad Paladugu break; 22174ba69dbSSiva Durga Prasad Paladugu default: 22274ba69dbSSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 22374ba69dbSSiva Durga Prasad Paladugu } 22474ba69dbSSiva Durga Prasad Paladugu } 2250cba6abbSSoren Brinkmann 226db3123b4SSiva Durga Prasad Paladugu return val; 22747e60cbdSMichal Simek } 22847e60cbdSMichal Simek 22983bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_VERSION_SIZE 9 23083bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_BIT 9 23183bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) 23283bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) 23383bf2ff0SSiva Durga Prasad Paladugu 23474ba69dbSSiva Durga Prasad Paladugu #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 23574ba69dbSSiva Durga Prasad Paladugu !defined(CONFIG_SPL_BUILD) 23647e60cbdSMichal Simek static char *zynqmp_get_silicon_idcode_name(void) 23747e60cbdSMichal Simek { 238494fffe7SMichal Simek u32 i, id, ver; 23983bf2ff0SSiva Durga Prasad Paladugu char *buf; 24083bf2ff0SSiva Durga Prasad Paladugu static char name[ZYNQMP_VERSION_SIZE]; 24147e60cbdSMichal Simek 242db3123b4SSiva Durga Prasad Paladugu id = chip_id(IDCODE); 243494fffe7SMichal Simek ver = chip_id(IDCODE2); 244494fffe7SMichal Simek 24547e60cbdSMichal Simek for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 24683bf2ff0SSiva Durga Prasad Paladugu if ((zynqmp_devices[i].id == id) && 24783bf2ff0SSiva Durga Prasad Paladugu (zynqmp_devices[i].ver == (ver & 24883bf2ff0SSiva Durga Prasad Paladugu ZYNQMP_CSU_VERSION_MASK))) { 24983bf2ff0SSiva Durga Prasad Paladugu strncat(name, "zu", 2); 25083bf2ff0SSiva Durga Prasad Paladugu strncat(name, zynqmp_devices[i].name, 25183bf2ff0SSiva Durga Prasad Paladugu ZYNQMP_VERSION_SIZE - 3); 25283bf2ff0SSiva Durga Prasad Paladugu break; 25347e60cbdSMichal Simek } 25483bf2ff0SSiva Durga Prasad Paladugu } 25583bf2ff0SSiva Durga Prasad Paladugu 25683bf2ff0SSiva Durga Prasad Paladugu if (i >= ARRAY_SIZE(zynqmp_devices)) 25747e60cbdSMichal Simek return "unknown"; 25883bf2ff0SSiva Durga Prasad Paladugu 25983bf2ff0SSiva Durga Prasad Paladugu if (!zynqmp_devices[i].evexists) 26083bf2ff0SSiva Durga Prasad Paladugu return name; 26183bf2ff0SSiva Durga Prasad Paladugu 26283bf2ff0SSiva Durga Prasad Paladugu if (ver & ZYNQMP_PL_STATUS_MASK) 26383bf2ff0SSiva Durga Prasad Paladugu return name; 26483bf2ff0SSiva Durga Prasad Paladugu 26583bf2ff0SSiva Durga Prasad Paladugu if (strstr(name, "eg") || strstr(name, "ev")) { 26683bf2ff0SSiva Durga Prasad Paladugu buf = strstr(name, "e"); 26783bf2ff0SSiva Durga Prasad Paladugu *buf = '\0'; 26883bf2ff0SSiva Durga Prasad Paladugu } 26983bf2ff0SSiva Durga Prasad Paladugu 27083bf2ff0SSiva Durga Prasad Paladugu return name; 27147e60cbdSMichal Simek } 27247e60cbdSMichal Simek #endif 27347e60cbdSMichal Simek 274fb4000e8SMichal Simek int board_early_init_f(void) 275fb4000e8SMichal Simek { 276f32e79f1SMichal Simek int ret = 0; 277fb4000e8SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP) 278fb4000e8SMichal Simek zynqmp_pmufw_version(); 279fb4000e8SMichal Simek #endif 28055de0929SMichal Simek 28188f05a92SMichal Simek #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) 282f32e79f1SMichal Simek ret = psu_init(); 28355de0929SMichal Simek #endif 28455de0929SMichal Simek 285f32e79f1SMichal Simek return ret; 286fb4000e8SMichal Simek } 287fb4000e8SMichal Simek 28884c7204bSMichal Simek int board_init(void) 28984c7204bSMichal Simek { 290a0736efbSMichal Simek printf("EL Level:\tEL%d\n", current_el()); 291a0736efbSMichal Simek 29247e60cbdSMichal Simek #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 29347e60cbdSMichal Simek !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \ 29447e60cbdSMichal Simek defined(CONFIG_SPL_BUILD)) 29547e60cbdSMichal Simek if (current_el() != 3) { 29683bf2ff0SSiva Durga Prasad Paladugu zynqmppl.name = zynqmp_get_silicon_idcode_name(); 29747e60cbdSMichal Simek printf("Chip ID:\t%s\n", zynqmppl.name); 29847e60cbdSMichal Simek fpga_init(); 29947e60cbdSMichal Simek fpga_add(fpga_xilinx, &zynqmppl); 30047e60cbdSMichal Simek } 30147e60cbdSMichal Simek #endif 30247e60cbdSMichal Simek 30384c7204bSMichal Simek return 0; 30484c7204bSMichal Simek } 30584c7204bSMichal Simek 30684c7204bSMichal Simek int board_early_init_r(void) 30784c7204bSMichal Simek { 30884c7204bSMichal Simek u32 val; 30984c7204bSMichal Simek 310ec60a279SSiva Durga Prasad Paladugu if (current_el() != 3) 311ec60a279SSiva Durga Prasad Paladugu return 0; 312ec60a279SSiva Durga Prasad Paladugu 31390a35db4SMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 31490a35db4SMichal Simek val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 31590a35db4SMichal Simek 316ec60a279SSiva Durga Prasad Paladugu if (!val) { 31784c7204bSMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 31884c7204bSMichal Simek val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 31984c7204bSMichal Simek writel(val, &crlapb_base->timestamp_ref_ctrl); 32084c7204bSMichal Simek 3210785dfd8SMichal Simek /* Program freq register in System counter */ 3220785dfd8SMichal Simek writel(zynqmp_get_system_timer_freq(), 3230785dfd8SMichal Simek &iou_scntr_secure->base_frequency_id_register); 3240785dfd8SMichal Simek /* And enable system counter */ 3250785dfd8SMichal Simek writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, 3260785dfd8SMichal Simek &iou_scntr_secure->counter_control_register); 3270785dfd8SMichal Simek } 32884c7204bSMichal Simek return 0; 32984c7204bSMichal Simek } 33084c7204bSMichal Simek 3316919b4bfSMichal Simek int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) 3326919b4bfSMichal Simek { 3336919b4bfSMichal Simek #if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \ 3346919b4bfSMichal Simek defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \ 3356919b4bfSMichal Simek defined(CONFIG_ZYNQ_EEPROM_BUS) 3366919b4bfSMichal Simek i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS); 3376919b4bfSMichal Simek 3386919b4bfSMichal Simek if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR, 3396919b4bfSMichal Simek CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET, 3406919b4bfSMichal Simek ethaddr, 6)) 3416919b4bfSMichal Simek printf("I2C EEPROM MAC address read failed\n"); 3426919b4bfSMichal Simek #endif 3436919b4bfSMichal Simek 3446919b4bfSMichal Simek return 0; 3456919b4bfSMichal Simek } 3466919b4bfSMichal Simek 34751916864SNitin Jain unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, 34851916864SNitin Jain char * const argv[]) 34951916864SNitin Jain { 35051916864SNitin Jain int ret = 0; 35151916864SNitin Jain 35251916864SNitin Jain if (current_el() > 1) { 35351916864SNitin Jain smp_kick_all_cpus(); 35451916864SNitin Jain dcache_disable(); 35551916864SNitin Jain armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, 35651916864SNitin Jain ES_TO_AARCH64); 35751916864SNitin Jain } else { 35851916864SNitin Jain printf("FAIL: current EL is not above EL1\n"); 35951916864SNitin Jain ret = EINVAL; 36051916864SNitin Jain } 36151916864SNitin Jain return ret; 36251916864SNitin Jain } 36351916864SNitin Jain 3648d59d7f6SMichal Simek #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) 36576b00acaSSimon Glass int dram_init_banksize(void) 366361a8799STom Rini { 367da3f003bSMichal Simek return fdtdec_setup_memory_banksize(); 3688d59d7f6SMichal Simek } 3698d59d7f6SMichal Simek 3708d59d7f6SMichal Simek int dram_init(void) 3718d59d7f6SMichal Simek { 372950f86caSNathan Rossi if (fdtdec_setup_memory_size() != 0) 373950f86caSNathan Rossi return -EINVAL; 3748d59d7f6SMichal Simek 3758d59d7f6SMichal Simek return 0; 3768d59d7f6SMichal Simek } 3778d59d7f6SMichal Simek #else 37884c7204bSMichal Simek int dram_init(void) 37984c7204bSMichal Simek { 380*61dc92a2SMichal Simek gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, 381*61dc92a2SMichal Simek CONFIG_SYS_SDRAM_SIZE); 38284c7204bSMichal Simek 38384c7204bSMichal Simek return 0; 38484c7204bSMichal Simek } 3858d59d7f6SMichal Simek #endif 38684c7204bSMichal Simek 38784c7204bSMichal Simek void reset_cpu(ulong addr) 38884c7204bSMichal Simek { 38984c7204bSMichal Simek } 39084c7204bSMichal Simek 39184c7204bSMichal Simek int board_late_init(void) 39284c7204bSMichal Simek { 39384c7204bSMichal Simek u32 reg = 0; 39484c7204bSMichal Simek u8 bootmode; 395b72894f1SMichal Simek const char *mode; 396b72894f1SMichal Simek char *new_targets; 39701c42d3dSSiva Durga Prasad Paladugu char *env_targets; 398d1db89f4SSiva Durga Prasad Paladugu int ret; 399b72894f1SMichal Simek 400b72894f1SMichal Simek if (!(gd->flags & GD_FLG_ENV_DEFAULT)) { 401b72894f1SMichal Simek debug("Saved variables - Skipping\n"); 402b72894f1SMichal Simek return 0; 403b72894f1SMichal Simek } 40484c7204bSMichal Simek 405d1db89f4SSiva Durga Prasad Paladugu ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); 406d1db89f4SSiva Durga Prasad Paladugu if (ret) 407d1db89f4SSiva Durga Prasad Paladugu return -EINVAL; 408d1db89f4SSiva Durga Prasad Paladugu 40947359a03SMichal Simek if (reg >> BOOT_MODE_ALT_SHIFT) 41047359a03SMichal Simek reg >>= BOOT_MODE_ALT_SHIFT; 41147359a03SMichal Simek 41284c7204bSMichal Simek bootmode = reg & BOOT_MODES_MASK; 41384c7204bSMichal Simek 414fb90917cSMichal Simek puts("Bootmode: "); 41584c7204bSMichal Simek switch (bootmode) { 416d58fc12eSMichal Simek case USB_MODE: 417d58fc12eSMichal Simek puts("USB_MODE\n"); 418d58fc12eSMichal Simek mode = "usb"; 41907656ba5SMichal Simek env_set("modeboot", "usb_dfu_spl"); 420d58fc12eSMichal Simek break; 4210a5bcc8cSSiva Durga Prasad Paladugu case JTAG_MODE: 422fb90917cSMichal Simek puts("JTAG_MODE\n"); 423b72894f1SMichal Simek mode = "pxe dhcp"; 42407656ba5SMichal Simek env_set("modeboot", "jtagboot"); 4250a5bcc8cSSiva Durga Prasad Paladugu break; 4260a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_24BIT: 4270a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_32BIT: 428b72894f1SMichal Simek mode = "qspi0"; 429fb90917cSMichal Simek puts("QSPI_MODE\n"); 43007656ba5SMichal Simek env_set("modeboot", "qspiboot"); 4310a5bcc8cSSiva Durga Prasad Paladugu break; 43239c56f55SMichal Simek case EMMC_MODE: 43378678feeSMichal Simek puts("EMMC_MODE\n"); 434b72894f1SMichal Simek mode = "mmc0"; 43507656ba5SMichal Simek env_set("modeboot", "emmcboot"); 43678678feeSMichal Simek break; 43778678feeSMichal Simek case SD_MODE: 438fb90917cSMichal Simek puts("SD_MODE\n"); 439b72894f1SMichal Simek mode = "mmc0"; 44007656ba5SMichal Simek env_set("modeboot", "sdboot"); 44184c7204bSMichal Simek break; 442e1992276SSiva Durga Prasad Paladugu case SD1_LSHFT_MODE: 443e1992276SSiva Durga Prasad Paladugu puts("LVL_SHFT_"); 444e1992276SSiva Durga Prasad Paladugu /* fall through */ 445af813acdSMichal Simek case SD_MODE1: 446fb90917cSMichal Simek puts("SD_MODE1\n"); 4472d9925bcSMichal Simek #if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1) 448b72894f1SMichal Simek mode = "mmc1"; 44907656ba5SMichal Simek env_set("sdbootdev", "1"); 450b72894f1SMichal Simek #else 451b72894f1SMichal Simek mode = "mmc0"; 4522d9925bcSMichal Simek #endif 45307656ba5SMichal Simek env_set("modeboot", "sdboot"); 454af813acdSMichal Simek break; 455af813acdSMichal Simek case NAND_MODE: 456fb90917cSMichal Simek puts("NAND_MODE\n"); 457b72894f1SMichal Simek mode = "nand0"; 45807656ba5SMichal Simek env_set("modeboot", "nandboot"); 459af813acdSMichal Simek break; 46084c7204bSMichal Simek default: 461b72894f1SMichal Simek mode = ""; 46284c7204bSMichal Simek printf("Invalid Boot Mode:0x%x\n", bootmode); 46384c7204bSMichal Simek break; 46484c7204bSMichal Simek } 46584c7204bSMichal Simek 466b72894f1SMichal Simek /* 467b72894f1SMichal Simek * One terminating char + one byte for space between mode 468b72894f1SMichal Simek * and default boot_targets 469b72894f1SMichal Simek */ 47001c42d3dSSiva Durga Prasad Paladugu env_targets = env_get("boot_targets"); 47101c42d3dSSiva Durga Prasad Paladugu if (env_targets) { 472b72894f1SMichal Simek new_targets = calloc(1, strlen(mode) + 47301c42d3dSSiva Durga Prasad Paladugu strlen(env_targets) + 2); 47401c42d3dSSiva Durga Prasad Paladugu sprintf(new_targets, "%s %s", mode, env_targets); 47501c42d3dSSiva Durga Prasad Paladugu } else { 47601c42d3dSSiva Durga Prasad Paladugu new_targets = calloc(1, strlen(mode) + 2); 47701c42d3dSSiva Durga Prasad Paladugu sprintf(new_targets, "%s", mode); 47801c42d3dSSiva Durga Prasad Paladugu } 479b72894f1SMichal Simek 480382bee57SSimon Glass env_set("boot_targets", new_targets); 481b72894f1SMichal Simek 48284c7204bSMichal Simek return 0; 48384c7204bSMichal Simek } 48484696ff5SSiva Durga Prasad Paladugu 48584696ff5SSiva Durga Prasad Paladugu int checkboard(void) 48684696ff5SSiva Durga Prasad Paladugu { 4875af08556SMichal Simek puts("Board: Xilinx ZynqMP\n"); 48884696ff5SSiva Durga Prasad Paladugu return 0; 48984696ff5SSiva Durga Prasad Paladugu } 49016fa00a7SSiva Durga Prasad Paladugu 49116fa00a7SSiva Durga Prasad Paladugu #ifdef CONFIG_USB_DWC3 492275bd6d1SMichal Simek static struct dwc3_device dwc3_device_data0 = { 49316fa00a7SSiva Durga Prasad Paladugu .maximum_speed = USB_SPEED_HIGH, 49416fa00a7SSiva Durga Prasad Paladugu .base = ZYNQMP_USB0_XHCI_BASEADDR, 49516fa00a7SSiva Durga Prasad Paladugu .dr_mode = USB_DR_MODE_PERIPHERAL, 49616fa00a7SSiva Durga Prasad Paladugu .index = 0, 49716fa00a7SSiva Durga Prasad Paladugu }; 49816fa00a7SSiva Durga Prasad Paladugu 499275bd6d1SMichal Simek static struct dwc3_device dwc3_device_data1 = { 500275bd6d1SMichal Simek .maximum_speed = USB_SPEED_HIGH, 501275bd6d1SMichal Simek .base = ZYNQMP_USB1_XHCI_BASEADDR, 502275bd6d1SMichal Simek .dr_mode = USB_DR_MODE_PERIPHERAL, 503275bd6d1SMichal Simek .index = 1, 504275bd6d1SMichal Simek }; 505275bd6d1SMichal Simek 5069feff385SMichal Simek int usb_gadget_handle_interrupts(int index) 50716fa00a7SSiva Durga Prasad Paladugu { 5089feff385SMichal Simek dwc3_uboot_handle_interrupt(index); 50916fa00a7SSiva Durga Prasad Paladugu return 0; 51016fa00a7SSiva Durga Prasad Paladugu } 51116fa00a7SSiva Durga Prasad Paladugu 51216fa00a7SSiva Durga Prasad Paladugu int board_usb_init(int index, enum usb_init_type init) 51316fa00a7SSiva Durga Prasad Paladugu { 514275bd6d1SMichal Simek debug("%s: index %x\n", __func__, index); 515275bd6d1SMichal Simek 5168ecd50c8SMichal Simek #if defined(CONFIG_USB_GADGET_DOWNLOAD) 5178ecd50c8SMichal Simek g_dnl_set_serialnumber(CONFIG_SYS_CONFIG_NAME); 5188ecd50c8SMichal Simek #endif 5198ecd50c8SMichal Simek 520275bd6d1SMichal Simek switch (index) { 521275bd6d1SMichal Simek case 0: 522275bd6d1SMichal Simek return dwc3_uboot_init(&dwc3_device_data0); 523275bd6d1SMichal Simek case 1: 524275bd6d1SMichal Simek return dwc3_uboot_init(&dwc3_device_data1); 525275bd6d1SMichal Simek }; 526275bd6d1SMichal Simek 527275bd6d1SMichal Simek return -1; 52816fa00a7SSiva Durga Prasad Paladugu } 52916fa00a7SSiva Durga Prasad Paladugu 53016fa00a7SSiva Durga Prasad Paladugu int board_usb_cleanup(int index, enum usb_init_type init) 53116fa00a7SSiva Durga Prasad Paladugu { 53216fa00a7SSiva Durga Prasad Paladugu dwc3_uboot_exit(index); 53316fa00a7SSiva Durga Prasad Paladugu return 0; 53416fa00a7SSiva Durga Prasad Paladugu } 53516fa00a7SSiva Durga Prasad Paladugu #endif 536