183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+ 284c7204bSMichal Simek /* 384c7204bSMichal Simek * (C) Copyright 2014 - 2015 Xilinx, Inc. 484c7204bSMichal Simek * Michal Simek <michal.simek@xilinx.com> 584c7204bSMichal Simek */ 684c7204bSMichal Simek 784c7204bSMichal Simek #include <common.h> 8679b994aSMichal Simek #include <sata.h> 96fe6f135SMichal Simek #include <ahci.h> 106fe6f135SMichal Simek #include <scsi.h> 11b72894f1SMichal Simek #include <malloc.h> 124490e013SMichal Simek #include <wdt.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> 184490e013SMichal Simek #include <dm/uclass.h> 1916fa00a7SSiva Durga Prasad Paladugu #include <usb.h> 2016fa00a7SSiva Durga Prasad Paladugu #include <dwc3-uboot.h> 2147e60cbdSMichal Simek #include <zynqmppl.h> 226919b4bfSMichal Simek #include <i2c.h> 239feff385SMichal Simek #include <g_dnl.h> 2484c7204bSMichal Simek 2584c7204bSMichal Simek DECLARE_GLOBAL_DATA_PTR; 2684c7204bSMichal Simek 274490e013SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) 284490e013SMichal Simek static struct udevice *watchdog_dev; 294490e013SMichal Simek #endif 304490e013SMichal Simek 3147e60cbdSMichal Simek #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 3247e60cbdSMichal Simek !defined(CONFIG_SPL_BUILD) 3347e60cbdSMichal Simek static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC; 3447e60cbdSMichal Simek 3547e60cbdSMichal Simek static const struct { 368ebdf9efSMichal Simek u32 id; 37494fffe7SMichal Simek u32 ver; 3847e60cbdSMichal Simek char *name; 3983bf2ff0SSiva Durga Prasad Paladugu bool evexists; 4047e60cbdSMichal Simek } zynqmp_devices[] = { 4147e60cbdSMichal Simek { 4247e60cbdSMichal Simek .id = 0x10, 4347e60cbdSMichal Simek .name = "3eg", 4447e60cbdSMichal Simek }, 4547e60cbdSMichal Simek { 46494fffe7SMichal Simek .id = 0x10, 47494fffe7SMichal Simek .ver = 0x2c, 48494fffe7SMichal Simek .name = "3cg", 49494fffe7SMichal Simek }, 50494fffe7SMichal Simek { 5147e60cbdSMichal Simek .id = 0x11, 5247e60cbdSMichal Simek .name = "2eg", 5347e60cbdSMichal Simek }, 5447e60cbdSMichal Simek { 55494fffe7SMichal Simek .id = 0x11, 56494fffe7SMichal Simek .ver = 0x2c, 57494fffe7SMichal Simek .name = "2cg", 58494fffe7SMichal Simek }, 59494fffe7SMichal Simek { 6047e60cbdSMichal Simek .id = 0x20, 6147e60cbdSMichal Simek .name = "5ev", 6283bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 6347e60cbdSMichal Simek }, 6447e60cbdSMichal Simek { 65494fffe7SMichal Simek .id = 0x20, 66494fffe7SMichal Simek .ver = 0x100, 67494fffe7SMichal Simek .name = "5eg", 6883bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 69494fffe7SMichal Simek }, 70494fffe7SMichal Simek { 71494fffe7SMichal Simek .id = 0x20, 72494fffe7SMichal Simek .ver = 0x12c, 73494fffe7SMichal Simek .name = "5cg", 74494fffe7SMichal Simek }, 75494fffe7SMichal Simek { 7647e60cbdSMichal Simek .id = 0x21, 7747e60cbdSMichal Simek .name = "4ev", 7883bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 7947e60cbdSMichal Simek }, 8047e60cbdSMichal Simek { 81494fffe7SMichal Simek .id = 0x21, 82494fffe7SMichal Simek .ver = 0x100, 83494fffe7SMichal Simek .name = "4eg", 8483bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 85494fffe7SMichal Simek }, 86494fffe7SMichal Simek { 87494fffe7SMichal Simek .id = 0x21, 88494fffe7SMichal Simek .ver = 0x12c, 89494fffe7SMichal Simek .name = "4cg", 90494fffe7SMichal Simek }, 91494fffe7SMichal Simek { 9247e60cbdSMichal Simek .id = 0x30, 9347e60cbdSMichal Simek .name = "7ev", 9483bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 9547e60cbdSMichal Simek }, 9647e60cbdSMichal Simek { 97494fffe7SMichal Simek .id = 0x30, 98494fffe7SMichal Simek .ver = 0x100, 99494fffe7SMichal Simek .name = "7eg", 10083bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 101494fffe7SMichal Simek }, 102494fffe7SMichal Simek { 103494fffe7SMichal Simek .id = 0x30, 104494fffe7SMichal Simek .ver = 0x12c, 105494fffe7SMichal Simek .name = "7cg", 106494fffe7SMichal Simek }, 107494fffe7SMichal Simek { 10847e60cbdSMichal Simek .id = 0x38, 10947e60cbdSMichal Simek .name = "9eg", 11047e60cbdSMichal Simek }, 11147e60cbdSMichal Simek { 112494fffe7SMichal Simek .id = 0x38, 113494fffe7SMichal Simek .ver = 0x2c, 114494fffe7SMichal Simek .name = "9cg", 115494fffe7SMichal Simek }, 116494fffe7SMichal Simek { 11747e60cbdSMichal Simek .id = 0x39, 11847e60cbdSMichal Simek .name = "6eg", 11947e60cbdSMichal Simek }, 12047e60cbdSMichal Simek { 121494fffe7SMichal Simek .id = 0x39, 122494fffe7SMichal Simek .ver = 0x2c, 123494fffe7SMichal Simek .name = "6cg", 124494fffe7SMichal Simek }, 125494fffe7SMichal Simek { 12647e60cbdSMichal Simek .id = 0x40, 12747e60cbdSMichal Simek .name = "11eg", 12847e60cbdSMichal Simek }, 129494fffe7SMichal Simek { /* For testing purpose only */ 130494fffe7SMichal Simek .id = 0x50, 131494fffe7SMichal Simek .ver = 0x2c, 132494fffe7SMichal Simek .name = "15cg", 133494fffe7SMichal Simek }, 13447e60cbdSMichal Simek { 13547e60cbdSMichal Simek .id = 0x50, 13647e60cbdSMichal Simek .name = "15eg", 13747e60cbdSMichal Simek }, 13847e60cbdSMichal Simek { 13947e60cbdSMichal Simek .id = 0x58, 14047e60cbdSMichal Simek .name = "19eg", 14147e60cbdSMichal Simek }, 14247e60cbdSMichal Simek { 14347e60cbdSMichal Simek .id = 0x59, 14447e60cbdSMichal Simek .name = "17eg", 14547e60cbdSMichal Simek }, 146b030fedfSMichal Simek { 147b030fedfSMichal Simek .id = 0x61, 148b030fedfSMichal Simek .name = "21dr", 149b030fedfSMichal Simek }, 150b030fedfSMichal Simek { 151b030fedfSMichal Simek .id = 0x63, 152b030fedfSMichal Simek .name = "23dr", 153b030fedfSMichal Simek }, 154b030fedfSMichal Simek { 155b030fedfSMichal Simek .id = 0x65, 156b030fedfSMichal Simek .name = "25dr", 157b030fedfSMichal Simek }, 158b030fedfSMichal Simek { 159b030fedfSMichal Simek .id = 0x64, 160b030fedfSMichal Simek .name = "27dr", 161b030fedfSMichal Simek }, 162b030fedfSMichal Simek { 163b030fedfSMichal Simek .id = 0x60, 164b030fedfSMichal Simek .name = "28dr", 165b030fedfSMichal Simek }, 166b030fedfSMichal Simek { 167b030fedfSMichal Simek .id = 0x62, 168b030fedfSMichal Simek .name = "29dr", 169b030fedfSMichal Simek }, 17047e60cbdSMichal Simek }; 17174ba69dbSSiva Durga Prasad Paladugu #endif 17247e60cbdSMichal Simek 173f52bf5a3SSiva Durga Prasad Paladugu int chip_id(unsigned char id) 17447e60cbdSMichal Simek { 17547e60cbdSMichal Simek struct pt_regs regs; 17674ba69dbSSiva Durga Prasad Paladugu int val = -EINVAL; 17774ba69dbSSiva Durga Prasad Paladugu 17874ba69dbSSiva Durga Prasad Paladugu if (current_el() != 3) { 17947e60cbdSMichal Simek regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID; 18047e60cbdSMichal Simek regs.regs[1] = 0; 18147e60cbdSMichal Simek regs.regs[2] = 0; 18247e60cbdSMichal Simek regs.regs[3] = 0; 18347e60cbdSMichal Simek 18447e60cbdSMichal Simek smc_call(®s); 18547e60cbdSMichal Simek 1860cba6abbSSoren Brinkmann /* 1870cba6abbSSoren Brinkmann * SMC returns: 1880cba6abbSSoren Brinkmann * regs[0][31:0] = status of the operation 1890cba6abbSSoren Brinkmann * regs[0][63:32] = CSU.IDCODE register 1900cba6abbSSoren Brinkmann * regs[1][31:0] = CSU.version register 191494fffe7SMichal Simek * regs[1][63:32] = CSU.IDCODE2 register 1920cba6abbSSoren Brinkmann */ 193db3123b4SSiva Durga Prasad Paladugu switch (id) { 194db3123b4SSiva Durga Prasad Paladugu case IDCODE: 1950cba6abbSSoren Brinkmann regs.regs[0] = upper_32_bits(regs.regs[0]); 1960cba6abbSSoren Brinkmann regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 1970cba6abbSSoren Brinkmann ZYNQMP_CSU_IDCODE_SVD_MASK; 1980cba6abbSSoren Brinkmann regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 199db3123b4SSiva Durga Prasad Paladugu val = regs.regs[0]; 200db3123b4SSiva Durga Prasad Paladugu break; 201db3123b4SSiva Durga Prasad Paladugu case VERSION: 202db3123b4SSiva Durga Prasad Paladugu regs.regs[1] = lower_32_bits(regs.regs[1]); 203db3123b4SSiva Durga Prasad Paladugu regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK; 204db3123b4SSiva Durga Prasad Paladugu val = regs.regs[1]; 205db3123b4SSiva Durga Prasad Paladugu break; 206494fffe7SMichal Simek case IDCODE2: 207494fffe7SMichal Simek regs.regs[1] = lower_32_bits(regs.regs[1]); 208494fffe7SMichal Simek regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT; 209494fffe7SMichal Simek val = regs.regs[1]; 210494fffe7SMichal Simek break; 211db3123b4SSiva Durga Prasad Paladugu default: 212db3123b4SSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 213db3123b4SSiva Durga Prasad Paladugu } 21474ba69dbSSiva Durga Prasad Paladugu } else { 21574ba69dbSSiva Durga Prasad Paladugu switch (id) { 21674ba69dbSSiva Durga Prasad Paladugu case IDCODE: 21774ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_IDCODE_ADDR); 21874ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 21974ba69dbSSiva Durga Prasad Paladugu ZYNQMP_CSU_IDCODE_SVD_MASK; 22074ba69dbSSiva Durga Prasad Paladugu val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 22174ba69dbSSiva Durga Prasad Paladugu break; 22274ba69dbSSiva Durga Prasad Paladugu case VERSION: 22374ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_VER_ADDR); 22474ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_SILICON_VER_MASK; 22574ba69dbSSiva Durga Prasad Paladugu break; 22674ba69dbSSiva Durga Prasad Paladugu default: 22774ba69dbSSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 22874ba69dbSSiva Durga Prasad Paladugu } 22974ba69dbSSiva Durga Prasad Paladugu } 2300cba6abbSSoren Brinkmann 231db3123b4SSiva Durga Prasad Paladugu return val; 23247e60cbdSMichal Simek } 23347e60cbdSMichal Simek 23483bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_VERSION_SIZE 9 23583bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_BIT 9 23683bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) 23783bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) 23883bf2ff0SSiva Durga Prasad Paladugu 23974ba69dbSSiva Durga Prasad Paladugu #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 24074ba69dbSSiva Durga Prasad Paladugu !defined(CONFIG_SPL_BUILD) 24147e60cbdSMichal Simek static char *zynqmp_get_silicon_idcode_name(void) 24247e60cbdSMichal Simek { 243494fffe7SMichal Simek u32 i, id, ver; 24483bf2ff0SSiva Durga Prasad Paladugu char *buf; 24583bf2ff0SSiva Durga Prasad Paladugu static char name[ZYNQMP_VERSION_SIZE]; 24647e60cbdSMichal Simek 247db3123b4SSiva Durga Prasad Paladugu id = chip_id(IDCODE); 248494fffe7SMichal Simek ver = chip_id(IDCODE2); 249494fffe7SMichal Simek 25047e60cbdSMichal Simek for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 25183bf2ff0SSiva Durga Prasad Paladugu if ((zynqmp_devices[i].id == id) && 25283bf2ff0SSiva Durga Prasad Paladugu (zynqmp_devices[i].ver == (ver & 25383bf2ff0SSiva Durga Prasad Paladugu ZYNQMP_CSU_VERSION_MASK))) { 25483bf2ff0SSiva Durga Prasad Paladugu strncat(name, "zu", 2); 25583bf2ff0SSiva Durga Prasad Paladugu strncat(name, zynqmp_devices[i].name, 25683bf2ff0SSiva Durga Prasad Paladugu ZYNQMP_VERSION_SIZE - 3); 25783bf2ff0SSiva Durga Prasad Paladugu break; 25847e60cbdSMichal Simek } 25983bf2ff0SSiva Durga Prasad Paladugu } 26083bf2ff0SSiva Durga Prasad Paladugu 26183bf2ff0SSiva Durga Prasad Paladugu if (i >= ARRAY_SIZE(zynqmp_devices)) 26247e60cbdSMichal Simek return "unknown"; 26383bf2ff0SSiva Durga Prasad Paladugu 26483bf2ff0SSiva Durga Prasad Paladugu if (!zynqmp_devices[i].evexists) 26583bf2ff0SSiva Durga Prasad Paladugu return name; 26683bf2ff0SSiva Durga Prasad Paladugu 26783bf2ff0SSiva Durga Prasad Paladugu if (ver & ZYNQMP_PL_STATUS_MASK) 26883bf2ff0SSiva Durga Prasad Paladugu return name; 26983bf2ff0SSiva Durga Prasad Paladugu 27083bf2ff0SSiva Durga Prasad Paladugu if (strstr(name, "eg") || strstr(name, "ev")) { 27183bf2ff0SSiva Durga Prasad Paladugu buf = strstr(name, "e"); 27283bf2ff0SSiva Durga Prasad Paladugu *buf = '\0'; 27383bf2ff0SSiva Durga Prasad Paladugu } 27483bf2ff0SSiva Durga Prasad Paladugu 27583bf2ff0SSiva Durga Prasad Paladugu return name; 27647e60cbdSMichal Simek } 27747e60cbdSMichal Simek #endif 27847e60cbdSMichal Simek 279fb4000e8SMichal Simek int board_early_init_f(void) 280fb4000e8SMichal Simek { 281f32e79f1SMichal Simek int ret = 0; 282fb4000e8SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP) 283fb4000e8SMichal Simek zynqmp_pmufw_version(); 284fb4000e8SMichal Simek #endif 28555de0929SMichal Simek 28688f05a92SMichal Simek #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) 287f32e79f1SMichal Simek ret = psu_init(); 28855de0929SMichal Simek #endif 28955de0929SMichal Simek 2904490e013SMichal Simek #if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD) 2914490e013SMichal Simek /* bss is not cleared at time when watchdog_reset() is called */ 2924490e013SMichal Simek watchdog_dev = NULL; 2934490e013SMichal Simek #endif 2944490e013SMichal Simek 295f32e79f1SMichal Simek return ret; 296fb4000e8SMichal Simek } 297fb4000e8SMichal Simek 29884c7204bSMichal Simek int board_init(void) 29984c7204bSMichal Simek { 300a0736efbSMichal Simek printf("EL Level:\tEL%d\n", current_el()); 301a0736efbSMichal Simek 30247e60cbdSMichal Simek #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 30347e60cbdSMichal Simek !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \ 30447e60cbdSMichal Simek defined(CONFIG_SPL_BUILD)) 30547e60cbdSMichal Simek if (current_el() != 3) { 30683bf2ff0SSiva Durga Prasad Paladugu zynqmppl.name = zynqmp_get_silicon_idcode_name(); 30747e60cbdSMichal Simek printf("Chip ID:\t%s\n", zynqmppl.name); 30847e60cbdSMichal Simek fpga_init(); 30947e60cbdSMichal Simek fpga_add(fpga_xilinx, &zynqmppl); 31047e60cbdSMichal Simek } 31147e60cbdSMichal Simek #endif 31247e60cbdSMichal Simek 3134490e013SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) 3144490e013SMichal Simek if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { 3154490e013SMichal Simek puts("Watchdog: Not found!\n"); 3164490e013SMichal Simek } else { 3174490e013SMichal Simek wdt_start(watchdog_dev, 0, 0); 3184490e013SMichal Simek puts("Watchdog: Started\n"); 3194490e013SMichal Simek } 3204490e013SMichal Simek #endif 3214490e013SMichal Simek 32284c7204bSMichal Simek return 0; 32384c7204bSMichal Simek } 32484c7204bSMichal Simek 3254490e013SMichal Simek #ifdef CONFIG_WATCHDOG 3264490e013SMichal Simek /* Called by macro WATCHDOG_RESET */ 3274490e013SMichal Simek void watchdog_reset(void) 3284490e013SMichal Simek { 3294490e013SMichal Simek # if !defined(CONFIG_SPL_BUILD) 3304490e013SMichal Simek static ulong next_reset; 3314490e013SMichal Simek ulong now; 3324490e013SMichal Simek 3334490e013SMichal Simek if (!watchdog_dev) 3344490e013SMichal Simek return; 3354490e013SMichal Simek 3364490e013SMichal Simek now = timer_get_us(); 3374490e013SMichal Simek 3384490e013SMichal Simek /* Do not reset the watchdog too often */ 3394490e013SMichal Simek if (now > next_reset) { 3404490e013SMichal Simek wdt_reset(watchdog_dev); 3414490e013SMichal Simek next_reset = now + 1000; 3424490e013SMichal Simek } 3434490e013SMichal Simek # endif 3444490e013SMichal Simek } 3454490e013SMichal Simek #endif 3464490e013SMichal Simek 34784c7204bSMichal Simek int board_early_init_r(void) 34884c7204bSMichal Simek { 34984c7204bSMichal Simek u32 val; 35084c7204bSMichal Simek 351ec60a279SSiva Durga Prasad Paladugu if (current_el() != 3) 352ec60a279SSiva Durga Prasad Paladugu return 0; 353ec60a279SSiva Durga Prasad Paladugu 35490a35db4SMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 35590a35db4SMichal Simek val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 35690a35db4SMichal Simek 357ec60a279SSiva Durga Prasad Paladugu if (!val) { 35884c7204bSMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 35984c7204bSMichal Simek val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 36084c7204bSMichal Simek writel(val, &crlapb_base->timestamp_ref_ctrl); 36184c7204bSMichal Simek 3620785dfd8SMichal Simek /* Program freq register in System counter */ 3630785dfd8SMichal Simek writel(zynqmp_get_system_timer_freq(), 3640785dfd8SMichal Simek &iou_scntr_secure->base_frequency_id_register); 3650785dfd8SMichal Simek /* And enable system counter */ 3660785dfd8SMichal Simek writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, 3670785dfd8SMichal Simek &iou_scntr_secure->counter_control_register); 3680785dfd8SMichal Simek } 36984c7204bSMichal Simek return 0; 37084c7204bSMichal Simek } 37184c7204bSMichal Simek 3726919b4bfSMichal Simek int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) 3736919b4bfSMichal Simek { 3746919b4bfSMichal Simek #if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \ 3756919b4bfSMichal Simek defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \ 3766919b4bfSMichal Simek defined(CONFIG_ZYNQ_EEPROM_BUS) 3776919b4bfSMichal Simek i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS); 3786919b4bfSMichal Simek 3796919b4bfSMichal Simek if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR, 3806919b4bfSMichal Simek CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET, 3816919b4bfSMichal Simek ethaddr, 6)) 3826919b4bfSMichal Simek printf("I2C EEPROM MAC address read failed\n"); 3836919b4bfSMichal Simek #endif 3846919b4bfSMichal Simek 3856919b4bfSMichal Simek return 0; 3866919b4bfSMichal Simek } 3876919b4bfSMichal Simek 38851916864SNitin Jain unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, 38951916864SNitin Jain char * const argv[]) 39051916864SNitin Jain { 39151916864SNitin Jain int ret = 0; 39251916864SNitin Jain 39351916864SNitin Jain if (current_el() > 1) { 39451916864SNitin Jain smp_kick_all_cpus(); 39551916864SNitin Jain dcache_disable(); 39651916864SNitin Jain armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, 39751916864SNitin Jain ES_TO_AARCH64); 39851916864SNitin Jain } else { 39951916864SNitin Jain printf("FAIL: current EL is not above EL1\n"); 40051916864SNitin Jain ret = EINVAL; 40151916864SNitin Jain } 40251916864SNitin Jain return ret; 40351916864SNitin Jain } 40451916864SNitin Jain 4058d59d7f6SMichal Simek #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) 40676b00acaSSimon Glass int dram_init_banksize(void) 407361a8799STom Rini { 4080678941aSNitin Jain int ret; 4090678941aSNitin Jain 4100678941aSNitin Jain ret = fdtdec_setup_memory_banksize(); 4110678941aSNitin Jain if (ret) 4120678941aSNitin Jain return ret; 4130678941aSNitin Jain 4140678941aSNitin Jain mem_map_fill(); 4150678941aSNitin Jain 4160678941aSNitin Jain return 0; 4178d59d7f6SMichal Simek } 4188d59d7f6SMichal Simek 4198d59d7f6SMichal Simek int dram_init(void) 4208d59d7f6SMichal Simek { 421950f86caSNathan Rossi if (fdtdec_setup_memory_size() != 0) 422950f86caSNathan Rossi return -EINVAL; 4238d59d7f6SMichal Simek 4248d59d7f6SMichal Simek return 0; 4258d59d7f6SMichal Simek } 4268d59d7f6SMichal Simek #else 4270678941aSNitin Jain int dram_init_banksize(void) 4280678941aSNitin Jain { 4290678941aSNitin Jain #if defined(CONFIG_NR_DRAM_BANKS) 4300678941aSNitin Jain gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; 4310678941aSNitin Jain gd->bd->bi_dram[0].size = get_effective_memsize(); 4320678941aSNitin Jain #endif 4330678941aSNitin Jain 4340678941aSNitin Jain mem_map_fill(); 4350678941aSNitin Jain 4360678941aSNitin Jain return 0; 4370678941aSNitin Jain } 4380678941aSNitin Jain 43984c7204bSMichal Simek int dram_init(void) 44084c7204bSMichal Simek { 44161dc92a2SMichal Simek gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, 44261dc92a2SMichal Simek CONFIG_SYS_SDRAM_SIZE); 44384c7204bSMichal Simek 44484c7204bSMichal Simek return 0; 44584c7204bSMichal Simek } 4468d59d7f6SMichal Simek #endif 44784c7204bSMichal Simek 44884c7204bSMichal Simek void reset_cpu(ulong addr) 44984c7204bSMichal Simek { 45084c7204bSMichal Simek } 45184c7204bSMichal Simek 452*d348beaaSMichal Simek static const struct { 453*d348beaaSMichal Simek u32 bit; 454*d348beaaSMichal Simek const char *name; 455*d348beaaSMichal Simek } reset_reasons[] = { 456*d348beaaSMichal Simek { RESET_REASON_DEBUG_SYS, "DEBUG" }, 457*d348beaaSMichal Simek { RESET_REASON_SOFT, "SOFT" }, 458*d348beaaSMichal Simek { RESET_REASON_SRST, "SRST" }, 459*d348beaaSMichal Simek { RESET_REASON_PSONLY, "PS-ONLY" }, 460*d348beaaSMichal Simek { RESET_REASON_PMU, "PMU" }, 461*d348beaaSMichal Simek { RESET_REASON_INTERNAL, "INTERNAL" }, 462*d348beaaSMichal Simek { RESET_REASON_EXTERNAL, "EXTERNAL" }, 463*d348beaaSMichal Simek {} 464*d348beaaSMichal Simek }; 465*d348beaaSMichal Simek 466*d348beaaSMichal Simek static u32 reset_reason(void) 467*d348beaaSMichal Simek { 468*d348beaaSMichal Simek u32 ret; 469*d348beaaSMichal Simek int i; 470*d348beaaSMichal Simek const char *reason = NULL; 471*d348beaaSMichal Simek 472*d348beaaSMichal Simek ret = readl(&crlapb_base->reset_reason); 473*d348beaaSMichal Simek 474*d348beaaSMichal Simek puts("Reset reason:\t"); 475*d348beaaSMichal Simek 476*d348beaaSMichal Simek for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) { 477*d348beaaSMichal Simek if (ret & reset_reasons[i].bit) { 478*d348beaaSMichal Simek reason = reset_reasons[i].name; 479*d348beaaSMichal Simek printf("%s ", reset_reasons[i].name); 480*d348beaaSMichal Simek break; 481*d348beaaSMichal Simek } 482*d348beaaSMichal Simek } 483*d348beaaSMichal Simek 484*d348beaaSMichal Simek puts("\n"); 485*d348beaaSMichal Simek 486*d348beaaSMichal Simek env_set("reset_reason", reason); 487*d348beaaSMichal Simek 488*d348beaaSMichal Simek writel(~0, &crlapb_base->reset_reason); 489*d348beaaSMichal Simek 490*d348beaaSMichal Simek return ret; 491*d348beaaSMichal Simek } 492*d348beaaSMichal Simek 49384c7204bSMichal Simek int board_late_init(void) 49484c7204bSMichal Simek { 49584c7204bSMichal Simek u32 reg = 0; 49684c7204bSMichal Simek u8 bootmode; 4970478b0b9SMichal Simek int env_targets_len = 0; 498b72894f1SMichal Simek const char *mode; 499b72894f1SMichal Simek char *new_targets; 50001c42d3dSSiva Durga Prasad Paladugu char *env_targets; 501d1db89f4SSiva Durga Prasad Paladugu int ret; 502b72894f1SMichal Simek 503b72894f1SMichal Simek if (!(gd->flags & GD_FLG_ENV_DEFAULT)) { 504b72894f1SMichal Simek debug("Saved variables - Skipping\n"); 505b72894f1SMichal Simek return 0; 506b72894f1SMichal Simek } 50784c7204bSMichal Simek 508d1db89f4SSiva Durga Prasad Paladugu ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); 509d1db89f4SSiva Durga Prasad Paladugu if (ret) 510d1db89f4SSiva Durga Prasad Paladugu return -EINVAL; 511d1db89f4SSiva Durga Prasad Paladugu 51247359a03SMichal Simek if (reg >> BOOT_MODE_ALT_SHIFT) 51347359a03SMichal Simek reg >>= BOOT_MODE_ALT_SHIFT; 51447359a03SMichal Simek 51584c7204bSMichal Simek bootmode = reg & BOOT_MODES_MASK; 51684c7204bSMichal Simek 517fb90917cSMichal Simek puts("Bootmode: "); 51884c7204bSMichal Simek switch (bootmode) { 519d58fc12eSMichal Simek case USB_MODE: 520d58fc12eSMichal Simek puts("USB_MODE\n"); 521d58fc12eSMichal Simek mode = "usb"; 52207656ba5SMichal Simek env_set("modeboot", "usb_dfu_spl"); 523d58fc12eSMichal Simek break; 5240a5bcc8cSSiva Durga Prasad Paladugu case JTAG_MODE: 525fb90917cSMichal Simek puts("JTAG_MODE\n"); 526b72894f1SMichal Simek mode = "pxe dhcp"; 52707656ba5SMichal Simek env_set("modeboot", "jtagboot"); 5280a5bcc8cSSiva Durga Prasad Paladugu break; 5290a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_24BIT: 5300a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_32BIT: 531b72894f1SMichal Simek mode = "qspi0"; 532fb90917cSMichal Simek puts("QSPI_MODE\n"); 53307656ba5SMichal Simek env_set("modeboot", "qspiboot"); 5340a5bcc8cSSiva Durga Prasad Paladugu break; 53539c56f55SMichal Simek case EMMC_MODE: 53678678feeSMichal Simek puts("EMMC_MODE\n"); 537b72894f1SMichal Simek mode = "mmc0"; 53807656ba5SMichal Simek env_set("modeboot", "emmcboot"); 53978678feeSMichal Simek break; 54078678feeSMichal Simek case SD_MODE: 541fb90917cSMichal Simek puts("SD_MODE\n"); 542b72894f1SMichal Simek mode = "mmc0"; 54307656ba5SMichal Simek env_set("modeboot", "sdboot"); 54484c7204bSMichal Simek break; 545e1992276SSiva Durga Prasad Paladugu case SD1_LSHFT_MODE: 546e1992276SSiva Durga Prasad Paladugu puts("LVL_SHFT_"); 547e1992276SSiva Durga Prasad Paladugu /* fall through */ 548af813acdSMichal Simek case SD_MODE1: 549fb90917cSMichal Simek puts("SD_MODE1\n"); 5502d9925bcSMichal Simek #if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1) 551b72894f1SMichal Simek mode = "mmc1"; 55207656ba5SMichal Simek env_set("sdbootdev", "1"); 553b72894f1SMichal Simek #else 554b72894f1SMichal Simek mode = "mmc0"; 5552d9925bcSMichal Simek #endif 55607656ba5SMichal Simek env_set("modeboot", "sdboot"); 557af813acdSMichal Simek break; 558af813acdSMichal Simek case NAND_MODE: 559fb90917cSMichal Simek puts("NAND_MODE\n"); 560b72894f1SMichal Simek mode = "nand0"; 56107656ba5SMichal Simek env_set("modeboot", "nandboot"); 562af813acdSMichal Simek break; 56384c7204bSMichal Simek default: 564b72894f1SMichal Simek mode = ""; 56584c7204bSMichal Simek printf("Invalid Boot Mode:0x%x\n", bootmode); 56684c7204bSMichal Simek break; 56784c7204bSMichal Simek } 56884c7204bSMichal Simek 569b72894f1SMichal Simek /* 570b72894f1SMichal Simek * One terminating char + one byte for space between mode 571b72894f1SMichal Simek * and default boot_targets 572b72894f1SMichal Simek */ 57301c42d3dSSiva Durga Prasad Paladugu env_targets = env_get("boot_targets"); 5740478b0b9SMichal Simek if (env_targets) 5750478b0b9SMichal Simek env_targets_len = strlen(env_targets); 5760478b0b9SMichal Simek 5770478b0b9SMichal Simek new_targets = calloc(1, strlen(mode) + env_targets_len + 2); 5780478b0b9SMichal Simek 5790478b0b9SMichal Simek sprintf(new_targets, "%s %s", mode, 5800478b0b9SMichal Simek env_targets ? env_targets : ""); 581b72894f1SMichal Simek 582382bee57SSimon Glass env_set("boot_targets", new_targets); 583b72894f1SMichal Simek 584*d348beaaSMichal Simek reset_reason(); 585*d348beaaSMichal Simek 58684c7204bSMichal Simek return 0; 58784c7204bSMichal Simek } 58884696ff5SSiva Durga Prasad Paladugu 58984696ff5SSiva Durga Prasad Paladugu int checkboard(void) 59084696ff5SSiva Durga Prasad Paladugu { 5915af08556SMichal Simek puts("Board: Xilinx ZynqMP\n"); 59284696ff5SSiva Durga Prasad Paladugu return 0; 59384696ff5SSiva Durga Prasad Paladugu } 594