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> 182882b39dSMichal Simek #include <dm/device.h> 194490e013SMichal Simek #include <dm/uclass.h> 2016fa00a7SSiva Durga Prasad Paladugu #include <usb.h> 2116fa00a7SSiva Durga Prasad Paladugu #include <dwc3-uboot.h> 2247e60cbdSMichal Simek #include <zynqmppl.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", 745473f245SSiva Durga Prasad Paladugu .evexists = 1, 75494fffe7SMichal Simek }, 76494fffe7SMichal Simek { 7747e60cbdSMichal Simek .id = 0x21, 7847e60cbdSMichal Simek .name = "4ev", 7983bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 8047e60cbdSMichal Simek }, 8147e60cbdSMichal Simek { 82494fffe7SMichal Simek .id = 0x21, 83494fffe7SMichal Simek .ver = 0x100, 84494fffe7SMichal Simek .name = "4eg", 8583bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 86494fffe7SMichal Simek }, 87494fffe7SMichal Simek { 88494fffe7SMichal Simek .id = 0x21, 89494fffe7SMichal Simek .ver = 0x12c, 90494fffe7SMichal Simek .name = "4cg", 915473f245SSiva Durga Prasad Paladugu .evexists = 1, 92494fffe7SMichal Simek }, 93494fffe7SMichal Simek { 9447e60cbdSMichal Simek .id = 0x30, 9547e60cbdSMichal Simek .name = "7ev", 9683bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 9747e60cbdSMichal Simek }, 9847e60cbdSMichal Simek { 99494fffe7SMichal Simek .id = 0x30, 100494fffe7SMichal Simek .ver = 0x100, 101494fffe7SMichal Simek .name = "7eg", 10283bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 103494fffe7SMichal Simek }, 104494fffe7SMichal Simek { 105494fffe7SMichal Simek .id = 0x30, 106494fffe7SMichal Simek .ver = 0x12c, 107494fffe7SMichal Simek .name = "7cg", 1085473f245SSiva Durga Prasad Paladugu .evexists = 1, 109494fffe7SMichal Simek }, 110494fffe7SMichal Simek { 11147e60cbdSMichal Simek .id = 0x38, 11247e60cbdSMichal Simek .name = "9eg", 11347e60cbdSMichal Simek }, 11447e60cbdSMichal Simek { 115494fffe7SMichal Simek .id = 0x38, 116494fffe7SMichal Simek .ver = 0x2c, 117494fffe7SMichal Simek .name = "9cg", 118494fffe7SMichal Simek }, 119494fffe7SMichal Simek { 12047e60cbdSMichal Simek .id = 0x39, 12147e60cbdSMichal Simek .name = "6eg", 12247e60cbdSMichal Simek }, 12347e60cbdSMichal Simek { 124494fffe7SMichal Simek .id = 0x39, 125494fffe7SMichal Simek .ver = 0x2c, 126494fffe7SMichal Simek .name = "6cg", 127494fffe7SMichal Simek }, 128494fffe7SMichal Simek { 12947e60cbdSMichal Simek .id = 0x40, 13047e60cbdSMichal Simek .name = "11eg", 13147e60cbdSMichal Simek }, 132494fffe7SMichal Simek { /* For testing purpose only */ 133494fffe7SMichal Simek .id = 0x50, 134494fffe7SMichal Simek .ver = 0x2c, 135494fffe7SMichal Simek .name = "15cg", 136494fffe7SMichal Simek }, 13747e60cbdSMichal Simek { 13847e60cbdSMichal Simek .id = 0x50, 13947e60cbdSMichal Simek .name = "15eg", 14047e60cbdSMichal Simek }, 14147e60cbdSMichal Simek { 14247e60cbdSMichal Simek .id = 0x58, 14347e60cbdSMichal Simek .name = "19eg", 14447e60cbdSMichal Simek }, 14547e60cbdSMichal Simek { 14647e60cbdSMichal Simek .id = 0x59, 14747e60cbdSMichal Simek .name = "17eg", 14847e60cbdSMichal Simek }, 149b030fedfSMichal Simek { 150b030fedfSMichal Simek .id = 0x61, 151b030fedfSMichal Simek .name = "21dr", 152b030fedfSMichal Simek }, 153b030fedfSMichal Simek { 154b030fedfSMichal Simek .id = 0x63, 155b030fedfSMichal Simek .name = "23dr", 156b030fedfSMichal Simek }, 157b030fedfSMichal Simek { 158b030fedfSMichal Simek .id = 0x65, 159b030fedfSMichal Simek .name = "25dr", 160b030fedfSMichal Simek }, 161b030fedfSMichal Simek { 162b030fedfSMichal Simek .id = 0x64, 163b030fedfSMichal Simek .name = "27dr", 164b030fedfSMichal Simek }, 165b030fedfSMichal Simek { 166b030fedfSMichal Simek .id = 0x60, 167b030fedfSMichal Simek .name = "28dr", 168b030fedfSMichal Simek }, 169b030fedfSMichal Simek { 170b030fedfSMichal Simek .id = 0x62, 171b030fedfSMichal Simek .name = "29dr", 172b030fedfSMichal Simek }, 17347e60cbdSMichal Simek }; 17474ba69dbSSiva Durga Prasad Paladugu #endif 17547e60cbdSMichal Simek 176f52bf5a3SSiva Durga Prasad Paladugu int chip_id(unsigned char id) 17747e60cbdSMichal Simek { 17847e60cbdSMichal Simek struct pt_regs regs; 17974ba69dbSSiva Durga Prasad Paladugu int val = -EINVAL; 18074ba69dbSSiva Durga Prasad Paladugu 18174ba69dbSSiva Durga Prasad Paladugu if (current_el() != 3) { 18247e60cbdSMichal Simek regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID; 18347e60cbdSMichal Simek regs.regs[1] = 0; 18447e60cbdSMichal Simek regs.regs[2] = 0; 18547e60cbdSMichal Simek regs.regs[3] = 0; 18647e60cbdSMichal Simek 18747e60cbdSMichal Simek smc_call(®s); 18847e60cbdSMichal Simek 1890cba6abbSSoren Brinkmann /* 1900cba6abbSSoren Brinkmann * SMC returns: 1910cba6abbSSoren Brinkmann * regs[0][31:0] = status of the operation 1920cba6abbSSoren Brinkmann * regs[0][63:32] = CSU.IDCODE register 1930cba6abbSSoren Brinkmann * regs[1][31:0] = CSU.version register 194494fffe7SMichal Simek * regs[1][63:32] = CSU.IDCODE2 register 1950cba6abbSSoren Brinkmann */ 196db3123b4SSiva Durga Prasad Paladugu switch (id) { 197db3123b4SSiva Durga Prasad Paladugu case IDCODE: 1980cba6abbSSoren Brinkmann regs.regs[0] = upper_32_bits(regs.regs[0]); 1990cba6abbSSoren Brinkmann regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 2000cba6abbSSoren Brinkmann ZYNQMP_CSU_IDCODE_SVD_MASK; 2010cba6abbSSoren Brinkmann regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 202db3123b4SSiva Durga Prasad Paladugu val = regs.regs[0]; 203db3123b4SSiva Durga Prasad Paladugu break; 204db3123b4SSiva Durga Prasad Paladugu case VERSION: 205db3123b4SSiva Durga Prasad Paladugu regs.regs[1] = lower_32_bits(regs.regs[1]); 206db3123b4SSiva Durga Prasad Paladugu regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK; 207db3123b4SSiva Durga Prasad Paladugu val = regs.regs[1]; 208db3123b4SSiva Durga Prasad Paladugu break; 209494fffe7SMichal Simek case IDCODE2: 210494fffe7SMichal Simek regs.regs[1] = lower_32_bits(regs.regs[1]); 211494fffe7SMichal Simek regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT; 212494fffe7SMichal Simek val = regs.regs[1]; 213494fffe7SMichal Simek break; 214db3123b4SSiva Durga Prasad Paladugu default: 215db3123b4SSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 216db3123b4SSiva Durga Prasad Paladugu } 21774ba69dbSSiva Durga Prasad Paladugu } else { 21874ba69dbSSiva Durga Prasad Paladugu switch (id) { 21974ba69dbSSiva Durga Prasad Paladugu case IDCODE: 22074ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_IDCODE_ADDR); 22174ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 22274ba69dbSSiva Durga Prasad Paladugu ZYNQMP_CSU_IDCODE_SVD_MASK; 22374ba69dbSSiva Durga Prasad Paladugu val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 22474ba69dbSSiva Durga Prasad Paladugu break; 22574ba69dbSSiva Durga Prasad Paladugu case VERSION: 22674ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_VER_ADDR); 22774ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_SILICON_VER_MASK; 22874ba69dbSSiva Durga Prasad Paladugu break; 22974ba69dbSSiva Durga Prasad Paladugu default: 23074ba69dbSSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 23174ba69dbSSiva Durga Prasad Paladugu } 23274ba69dbSSiva Durga Prasad Paladugu } 2330cba6abbSSoren Brinkmann 234db3123b4SSiva Durga Prasad Paladugu return val; 23547e60cbdSMichal Simek } 23647e60cbdSMichal Simek 23783bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_VERSION_SIZE 9 23883bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_BIT 9 2395473f245SSiva Durga Prasad Paladugu #define ZYNQMP_IPDIS_VCU_BIT 8 24083bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) 24183bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) 2425473f245SSiva Durga Prasad Paladugu #define ZYNQMP_CSU_VCUDIS_VER_MASK ZYNQMP_CSU_VERSION_MASK & \ 2435473f245SSiva Durga Prasad Paladugu ~BIT(ZYNQMP_IPDIS_VCU_BIT) 2445473f245SSiva Durga Prasad Paladugu #define MAX_VARIANTS_EV 3 24583bf2ff0SSiva Durga Prasad Paladugu 24674ba69dbSSiva Durga Prasad Paladugu #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 24774ba69dbSSiva Durga Prasad Paladugu !defined(CONFIG_SPL_BUILD) 24847e60cbdSMichal Simek static char *zynqmp_get_silicon_idcode_name(void) 24947e60cbdSMichal Simek { 2505473f245SSiva Durga Prasad Paladugu u32 i, id, ver, j; 25183bf2ff0SSiva Durga Prasad Paladugu char *buf; 25283bf2ff0SSiva Durga Prasad Paladugu static char name[ZYNQMP_VERSION_SIZE]; 25347e60cbdSMichal Simek 254db3123b4SSiva Durga Prasad Paladugu id = chip_id(IDCODE); 255494fffe7SMichal Simek ver = chip_id(IDCODE2); 256494fffe7SMichal Simek 25747e60cbdSMichal Simek for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 2585473f245SSiva Durga Prasad Paladugu if (zynqmp_devices[i].id == id) { 2595473f245SSiva Durga Prasad Paladugu if (zynqmp_devices[i].evexists && 2605473f245SSiva Durga Prasad Paladugu !(ver & ZYNQMP_PL_STATUS_MASK)) 2615473f245SSiva Durga Prasad Paladugu break; 2625473f245SSiva Durga Prasad Paladugu if (zynqmp_devices[i].ver == (ver & 2635473f245SSiva Durga Prasad Paladugu ZYNQMP_CSU_VERSION_MASK)) 26483bf2ff0SSiva Durga Prasad Paladugu break; 26547e60cbdSMichal Simek } 26683bf2ff0SSiva Durga Prasad Paladugu } 26783bf2ff0SSiva Durga Prasad Paladugu 26883bf2ff0SSiva Durga Prasad Paladugu if (i >= ARRAY_SIZE(zynqmp_devices)) 26947e60cbdSMichal Simek return "unknown"; 27083bf2ff0SSiva Durga Prasad Paladugu 2715473f245SSiva Durga Prasad Paladugu strncat(name, "zu", 2); 2725473f245SSiva Durga Prasad Paladugu if (!zynqmp_devices[i].evexists || 2735473f245SSiva Durga Prasad Paladugu (ver & ZYNQMP_PL_STATUS_MASK)) { 2745473f245SSiva Durga Prasad Paladugu strncat(name, zynqmp_devices[i].name, 2755473f245SSiva Durga Prasad Paladugu ZYNQMP_VERSION_SIZE - 3); 27683bf2ff0SSiva Durga Prasad Paladugu return name; 2775473f245SSiva Durga Prasad Paladugu } 27883bf2ff0SSiva Durga Prasad Paladugu 2795473f245SSiva Durga Prasad Paladugu /* 2805473f245SSiva Durga Prasad Paladugu * Here we are means, PL not powered up and ev variant 2815473f245SSiva Durga Prasad Paladugu * exists. So, we need to ignore VCU disable bit(8) in 2825473f245SSiva Durga Prasad Paladugu * version and findout if its CG or EG/EV variant. 2835473f245SSiva Durga Prasad Paladugu */ 2845473f245SSiva Durga Prasad Paladugu for (j = 0; j < MAX_VARIANTS_EV; j++, i++) { 2855473f245SSiva Durga Prasad Paladugu if ((zynqmp_devices[i].ver & ~BIT(ZYNQMP_IPDIS_VCU_BIT)) == 2865473f245SSiva Durga Prasad Paladugu (ver & ZYNQMP_CSU_VCUDIS_VER_MASK)) { 2875473f245SSiva Durga Prasad Paladugu strncat(name, zynqmp_devices[i].name, 2885473f245SSiva Durga Prasad Paladugu ZYNQMP_VERSION_SIZE - 3); 2895473f245SSiva Durga Prasad Paladugu break; 2905473f245SSiva Durga Prasad Paladugu } 2915473f245SSiva Durga Prasad Paladugu } 2925473f245SSiva Durga Prasad Paladugu 2935473f245SSiva Durga Prasad Paladugu if (j >= MAX_VARIANTS_EV) 2945473f245SSiva Durga Prasad Paladugu return "unknown"; 29583bf2ff0SSiva Durga Prasad Paladugu 29683bf2ff0SSiva Durga Prasad Paladugu if (strstr(name, "eg") || strstr(name, "ev")) { 29783bf2ff0SSiva Durga Prasad Paladugu buf = strstr(name, "e"); 29883bf2ff0SSiva Durga Prasad Paladugu *buf = '\0'; 29983bf2ff0SSiva Durga Prasad Paladugu } 30083bf2ff0SSiva Durga Prasad Paladugu 30183bf2ff0SSiva Durga Prasad Paladugu return name; 30247e60cbdSMichal Simek } 30347e60cbdSMichal Simek #endif 30447e60cbdSMichal Simek 305fb4000e8SMichal Simek int board_early_init_f(void) 306fb4000e8SMichal Simek { 307f32e79f1SMichal Simek int ret = 0; 308fb4000e8SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP) 309b94a8271SSiva Durga Prasad Paladugu u32 pm_api_version; 310b94a8271SSiva Durga Prasad Paladugu 311b94a8271SSiva Durga Prasad Paladugu pm_api_version = zynqmp_pmufw_version(); 312b94a8271SSiva Durga Prasad Paladugu printf("PMUFW:\tv%d.%d\n", 313b94a8271SSiva Durga Prasad Paladugu pm_api_version >> ZYNQMP_PM_VERSION_MAJOR_SHIFT, 314b94a8271SSiva Durga Prasad Paladugu pm_api_version & ZYNQMP_PM_VERSION_MINOR_MASK); 315b94a8271SSiva Durga Prasad Paladugu 316b94a8271SSiva Durga Prasad Paladugu if (pm_api_version < ZYNQMP_PM_VERSION) 317b94a8271SSiva Durga Prasad Paladugu panic("PMUFW version error. Expected: v%d.%d\n", 318b94a8271SSiva Durga Prasad Paladugu ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR); 319fb4000e8SMichal Simek #endif 32055de0929SMichal Simek 32188f05a92SMichal Simek #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) 322f32e79f1SMichal Simek ret = psu_init(); 32355de0929SMichal Simek #endif 32455de0929SMichal Simek 3254490e013SMichal Simek #if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD) 3264490e013SMichal Simek /* bss is not cleared at time when watchdog_reset() is called */ 3274490e013SMichal Simek watchdog_dev = NULL; 3284490e013SMichal Simek #endif 3294490e013SMichal Simek 330f32e79f1SMichal Simek return ret; 331fb4000e8SMichal Simek } 332fb4000e8SMichal Simek 33384c7204bSMichal Simek int board_init(void) 33484c7204bSMichal Simek { 335a0736efbSMichal Simek printf("EL Level:\tEL%d\n", current_el()); 336a0736efbSMichal Simek 33747e60cbdSMichal Simek #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 33847e60cbdSMichal Simek !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \ 33947e60cbdSMichal Simek defined(CONFIG_SPL_BUILD)) 34047e60cbdSMichal Simek if (current_el() != 3) { 34183bf2ff0SSiva Durga Prasad Paladugu zynqmppl.name = zynqmp_get_silicon_idcode_name(); 34247e60cbdSMichal Simek printf("Chip ID:\t%s\n", zynqmppl.name); 34347e60cbdSMichal Simek fpga_init(); 34447e60cbdSMichal Simek fpga_add(fpga_xilinx, &zynqmppl); 34547e60cbdSMichal Simek } 34647e60cbdSMichal Simek #endif 34747e60cbdSMichal Simek 3484490e013SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) 3491fbca0dbSMichal Simek if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) { 3501fbca0dbSMichal Simek debug("Watchdog: Not found by seq!\n"); 3514490e013SMichal Simek if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { 3524490e013SMichal Simek puts("Watchdog: Not found!\n"); 3531fbca0dbSMichal Simek return 0; 3541fbca0dbSMichal Simek } 3551fbca0dbSMichal Simek } 3561fbca0dbSMichal Simek 3574490e013SMichal Simek wdt_start(watchdog_dev, 0, 0); 3584490e013SMichal Simek puts("Watchdog: Started\n"); 3594490e013SMichal Simek #endif 3604490e013SMichal Simek 36184c7204bSMichal Simek return 0; 36284c7204bSMichal Simek } 36384c7204bSMichal Simek 3644490e013SMichal Simek #ifdef CONFIG_WATCHDOG 3654490e013SMichal Simek /* Called by macro WATCHDOG_RESET */ 3664490e013SMichal Simek void watchdog_reset(void) 3674490e013SMichal Simek { 3684490e013SMichal Simek # if !defined(CONFIG_SPL_BUILD) 3694490e013SMichal Simek static ulong next_reset; 3704490e013SMichal Simek ulong now; 3714490e013SMichal Simek 3724490e013SMichal Simek if (!watchdog_dev) 3734490e013SMichal Simek return; 3744490e013SMichal Simek 3754490e013SMichal Simek now = timer_get_us(); 3764490e013SMichal Simek 3774490e013SMichal Simek /* Do not reset the watchdog too often */ 3784490e013SMichal Simek if (now > next_reset) { 3794490e013SMichal Simek wdt_reset(watchdog_dev); 3804490e013SMichal Simek next_reset = now + 1000; 3814490e013SMichal Simek } 3824490e013SMichal Simek # endif 3834490e013SMichal Simek } 3844490e013SMichal Simek #endif 3854490e013SMichal Simek 38684c7204bSMichal Simek int board_early_init_r(void) 38784c7204bSMichal Simek { 38884c7204bSMichal Simek u32 val; 38984c7204bSMichal Simek 390ec60a279SSiva Durga Prasad Paladugu if (current_el() != 3) 391ec60a279SSiva Durga Prasad Paladugu return 0; 392ec60a279SSiva Durga Prasad Paladugu 39390a35db4SMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 39490a35db4SMichal Simek val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 39590a35db4SMichal Simek 396ec60a279SSiva Durga Prasad Paladugu if (!val) { 39784c7204bSMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 39884c7204bSMichal Simek val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 39984c7204bSMichal Simek writel(val, &crlapb_base->timestamp_ref_ctrl); 40084c7204bSMichal Simek 4010785dfd8SMichal Simek /* Program freq register in System counter */ 4020785dfd8SMichal Simek writel(zynqmp_get_system_timer_freq(), 4030785dfd8SMichal Simek &iou_scntr_secure->base_frequency_id_register); 4040785dfd8SMichal Simek /* And enable system counter */ 4050785dfd8SMichal Simek writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, 4060785dfd8SMichal Simek &iou_scntr_secure->counter_control_register); 4070785dfd8SMichal Simek } 40884c7204bSMichal Simek return 0; 40984c7204bSMichal Simek } 41084c7204bSMichal Simek 41151916864SNitin Jain unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, 41251916864SNitin Jain char * const argv[]) 41351916864SNitin Jain { 41451916864SNitin Jain int ret = 0; 41551916864SNitin Jain 41651916864SNitin Jain if (current_el() > 1) { 41751916864SNitin Jain smp_kick_all_cpus(); 41851916864SNitin Jain dcache_disable(); 41951916864SNitin Jain armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, 42051916864SNitin Jain ES_TO_AARCH64); 42151916864SNitin Jain } else { 42251916864SNitin Jain printf("FAIL: current EL is not above EL1\n"); 42351916864SNitin Jain ret = EINVAL; 42451916864SNitin Jain } 42551916864SNitin Jain return ret; 42651916864SNitin Jain } 42751916864SNitin Jain 4288d59d7f6SMichal Simek #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) 42976b00acaSSimon Glass int dram_init_banksize(void) 430361a8799STom Rini { 4310678941aSNitin Jain int ret; 4320678941aSNitin Jain 4330678941aSNitin Jain ret = fdtdec_setup_memory_banksize(); 4340678941aSNitin Jain if (ret) 4350678941aSNitin Jain return ret; 4360678941aSNitin Jain 4370678941aSNitin Jain mem_map_fill(); 4380678941aSNitin Jain 4390678941aSNitin Jain return 0; 4408d59d7f6SMichal Simek } 4418d59d7f6SMichal Simek 4428d59d7f6SMichal Simek int dram_init(void) 4438d59d7f6SMichal Simek { 44412308b12SSiva Durga Prasad Paladugu if (fdtdec_setup_mem_size_base() != 0) 445950f86caSNathan Rossi return -EINVAL; 4468d59d7f6SMichal Simek 4478d59d7f6SMichal Simek return 0; 4488d59d7f6SMichal Simek } 4498d59d7f6SMichal Simek #else 4500678941aSNitin Jain int dram_init_banksize(void) 4510678941aSNitin Jain { 4520678941aSNitin Jain #if defined(CONFIG_NR_DRAM_BANKS) 4530678941aSNitin Jain gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; 4540678941aSNitin Jain gd->bd->bi_dram[0].size = get_effective_memsize(); 4550678941aSNitin Jain #endif 4560678941aSNitin Jain 4570678941aSNitin Jain mem_map_fill(); 4580678941aSNitin Jain 4590678941aSNitin Jain return 0; 4600678941aSNitin Jain } 4610678941aSNitin Jain 46284c7204bSMichal Simek int dram_init(void) 46384c7204bSMichal Simek { 46461dc92a2SMichal Simek gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, 46561dc92a2SMichal Simek CONFIG_SYS_SDRAM_SIZE); 46684c7204bSMichal Simek 46784c7204bSMichal Simek return 0; 46884c7204bSMichal Simek } 4698d59d7f6SMichal Simek #endif 47084c7204bSMichal Simek 47184c7204bSMichal Simek void reset_cpu(ulong addr) 47284c7204bSMichal Simek { 47384c7204bSMichal Simek } 47484c7204bSMichal Simek 4750bf3f9cbSMichal Simek #if defined(CONFIG_BOARD_LATE_INIT) 476d348beaaSMichal Simek static const struct { 477d348beaaSMichal Simek u32 bit; 478d348beaaSMichal Simek const char *name; 479d348beaaSMichal Simek } reset_reasons[] = { 480d348beaaSMichal Simek { RESET_REASON_DEBUG_SYS, "DEBUG" }, 481d348beaaSMichal Simek { RESET_REASON_SOFT, "SOFT" }, 482d348beaaSMichal Simek { RESET_REASON_SRST, "SRST" }, 483d348beaaSMichal Simek { RESET_REASON_PSONLY, "PS-ONLY" }, 484d348beaaSMichal Simek { RESET_REASON_PMU, "PMU" }, 485d348beaaSMichal Simek { RESET_REASON_INTERNAL, "INTERNAL" }, 486d348beaaSMichal Simek { RESET_REASON_EXTERNAL, "EXTERNAL" }, 487d348beaaSMichal Simek {} 488d348beaaSMichal Simek }; 489d348beaaSMichal Simek 490d348beaaSMichal Simek static u32 reset_reason(void) 491d348beaaSMichal Simek { 492d348beaaSMichal Simek u32 ret; 493d348beaaSMichal Simek int i; 494d348beaaSMichal Simek const char *reason = NULL; 495d348beaaSMichal Simek 496d348beaaSMichal Simek ret = readl(&crlapb_base->reset_reason); 497d348beaaSMichal Simek 498d348beaaSMichal Simek puts("Reset reason:\t"); 499d348beaaSMichal Simek 500d348beaaSMichal Simek for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) { 501d348beaaSMichal Simek if (ret & reset_reasons[i].bit) { 502d348beaaSMichal Simek reason = reset_reasons[i].name; 503d348beaaSMichal Simek printf("%s ", reset_reasons[i].name); 504d348beaaSMichal Simek break; 505d348beaaSMichal Simek } 506d348beaaSMichal Simek } 507d348beaaSMichal Simek 508d348beaaSMichal Simek puts("\n"); 509d348beaaSMichal Simek 510d348beaaSMichal Simek env_set("reset_reason", reason); 511d348beaaSMichal Simek 512d348beaaSMichal Simek writel(~0, &crlapb_base->reset_reason); 513d348beaaSMichal Simek 514d348beaaSMichal Simek return ret; 515d348beaaSMichal Simek } 516d348beaaSMichal Simek 517*91d7e0c4SMichal Simek static int set_fdtfile(void) 518*91d7e0c4SMichal Simek { 519*91d7e0c4SMichal Simek char *compatible, *fdtfile; 520*91d7e0c4SMichal Simek const char *suffix = ".dtb"; 521*91d7e0c4SMichal Simek const char *vendor = "xilinx/"; 522*91d7e0c4SMichal Simek 523*91d7e0c4SMichal Simek if (env_get("fdtfile")) 524*91d7e0c4SMichal Simek return 0; 525*91d7e0c4SMichal Simek 526*91d7e0c4SMichal Simek compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", NULL); 527*91d7e0c4SMichal Simek if (compatible) { 528*91d7e0c4SMichal Simek debug("Compatible: %s\n", compatible); 529*91d7e0c4SMichal Simek 530*91d7e0c4SMichal Simek /* Discard vendor prefix */ 531*91d7e0c4SMichal Simek strsep(&compatible, ","); 532*91d7e0c4SMichal Simek 533*91d7e0c4SMichal Simek fdtfile = calloc(1, strlen(vendor) + strlen(compatible) + 534*91d7e0c4SMichal Simek strlen(suffix) + 1); 535*91d7e0c4SMichal Simek if (!fdtfile) 536*91d7e0c4SMichal Simek return -ENOMEM; 537*91d7e0c4SMichal Simek 538*91d7e0c4SMichal Simek sprintf(fdtfile, "%s%s%s", vendor, compatible, suffix); 539*91d7e0c4SMichal Simek 540*91d7e0c4SMichal Simek env_set("fdtfile", fdtfile); 541*91d7e0c4SMichal Simek free(fdtfile); 542*91d7e0c4SMichal Simek } 543*91d7e0c4SMichal Simek 544*91d7e0c4SMichal Simek return 0; 545*91d7e0c4SMichal Simek } 546*91d7e0c4SMichal Simek 54784c7204bSMichal Simek int board_late_init(void) 54884c7204bSMichal Simek { 54984c7204bSMichal Simek u32 reg = 0; 55084c7204bSMichal Simek u8 bootmode; 5512882b39dSMichal Simek struct udevice *dev; 5522882b39dSMichal Simek int bootseq = -1; 5532882b39dSMichal Simek int bootseq_len = 0; 5540478b0b9SMichal Simek int env_targets_len = 0; 555b72894f1SMichal Simek const char *mode; 556b72894f1SMichal Simek char *new_targets; 55701c42d3dSSiva Durga Prasad Paladugu char *env_targets; 558d1db89f4SSiva Durga Prasad Paladugu int ret; 559b72894f1SMichal Simek 560e615f39eSMichal Simek #if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD) 561e615f39eSMichal Simek usb_ether_init(); 562e615f39eSMichal Simek #endif 563e615f39eSMichal Simek 564b72894f1SMichal Simek if (!(gd->flags & GD_FLG_ENV_DEFAULT)) { 565b72894f1SMichal Simek debug("Saved variables - Skipping\n"); 566b72894f1SMichal Simek return 0; 567b72894f1SMichal Simek } 56884c7204bSMichal Simek 569*91d7e0c4SMichal Simek ret = set_fdtfile(); 570*91d7e0c4SMichal Simek if (ret) 571*91d7e0c4SMichal Simek return ret; 572*91d7e0c4SMichal Simek 573d1db89f4SSiva Durga Prasad Paladugu ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); 574d1db89f4SSiva Durga Prasad Paladugu if (ret) 575d1db89f4SSiva Durga Prasad Paladugu return -EINVAL; 576d1db89f4SSiva Durga Prasad Paladugu 57747359a03SMichal Simek if (reg >> BOOT_MODE_ALT_SHIFT) 57847359a03SMichal Simek reg >>= BOOT_MODE_ALT_SHIFT; 57947359a03SMichal Simek 58084c7204bSMichal Simek bootmode = reg & BOOT_MODES_MASK; 58184c7204bSMichal Simek 582fb90917cSMichal Simek puts("Bootmode: "); 58384c7204bSMichal Simek switch (bootmode) { 584d58fc12eSMichal Simek case USB_MODE: 585d58fc12eSMichal Simek puts("USB_MODE\n"); 586d58fc12eSMichal Simek mode = "usb"; 58707656ba5SMichal Simek env_set("modeboot", "usb_dfu_spl"); 588d58fc12eSMichal Simek break; 5890a5bcc8cSSiva Durga Prasad Paladugu case JTAG_MODE: 590fb90917cSMichal Simek puts("JTAG_MODE\n"); 591b72894f1SMichal Simek mode = "pxe dhcp"; 59207656ba5SMichal Simek env_set("modeboot", "jtagboot"); 5930a5bcc8cSSiva Durga Prasad Paladugu break; 5940a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_24BIT: 5950a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_32BIT: 596b72894f1SMichal Simek mode = "qspi0"; 597fb90917cSMichal Simek puts("QSPI_MODE\n"); 59807656ba5SMichal Simek env_set("modeboot", "qspiboot"); 5990a5bcc8cSSiva Durga Prasad Paladugu break; 60039c56f55SMichal Simek case EMMC_MODE: 60178678feeSMichal Simek puts("EMMC_MODE\n"); 602b72894f1SMichal Simek mode = "mmc0"; 60307656ba5SMichal Simek env_set("modeboot", "emmcboot"); 60478678feeSMichal Simek break; 60578678feeSMichal Simek case SD_MODE: 606fb90917cSMichal Simek puts("SD_MODE\n"); 6072882b39dSMichal Simek if (uclass_get_device_by_name(UCLASS_MMC, 608e7c9de66SSiva Durga Prasad Paladugu "mmc@ff160000", &dev) && 609e7c9de66SSiva Durga Prasad Paladugu uclass_get_device_by_name(UCLASS_MMC, 6102882b39dSMichal Simek "sdhci@ff160000", &dev)) { 6112882b39dSMichal Simek puts("Boot from SD0 but without SD0 enabled!\n"); 6122882b39dSMichal Simek return -1; 6132882b39dSMichal Simek } 6142882b39dSMichal Simek debug("mmc0 device found at %p, seq %d\n", dev, dev->seq); 6152882b39dSMichal Simek 6162882b39dSMichal Simek mode = "mmc"; 6172882b39dSMichal Simek bootseq = dev->seq; 61807656ba5SMichal Simek env_set("modeboot", "sdboot"); 61984c7204bSMichal Simek break; 620e1992276SSiva Durga Prasad Paladugu case SD1_LSHFT_MODE: 621e1992276SSiva Durga Prasad Paladugu puts("LVL_SHFT_"); 622e1992276SSiva Durga Prasad Paladugu /* fall through */ 623af813acdSMichal Simek case SD_MODE1: 624fb90917cSMichal Simek puts("SD_MODE1\n"); 6252882b39dSMichal Simek if (uclass_get_device_by_name(UCLASS_MMC, 626e7c9de66SSiva Durga Prasad Paladugu "mmc@ff170000", &dev) && 627e7c9de66SSiva Durga Prasad Paladugu uclass_get_device_by_name(UCLASS_MMC, 6282882b39dSMichal Simek "sdhci@ff170000", &dev)) { 6292882b39dSMichal Simek puts("Boot from SD1 but without SD1 enabled!\n"); 6302882b39dSMichal Simek return -1; 6312882b39dSMichal Simek } 6322882b39dSMichal Simek debug("mmc1 device found at %p, seq %d\n", dev, dev->seq); 6332882b39dSMichal Simek 6342882b39dSMichal Simek mode = "mmc"; 6352882b39dSMichal Simek bootseq = dev->seq; 63607656ba5SMichal Simek env_set("modeboot", "sdboot"); 637af813acdSMichal Simek break; 638af813acdSMichal Simek case NAND_MODE: 639fb90917cSMichal Simek puts("NAND_MODE\n"); 640b72894f1SMichal Simek mode = "nand0"; 64107656ba5SMichal Simek env_set("modeboot", "nandboot"); 642af813acdSMichal Simek break; 64384c7204bSMichal Simek default: 644b72894f1SMichal Simek mode = ""; 64584c7204bSMichal Simek printf("Invalid Boot Mode:0x%x\n", bootmode); 64684c7204bSMichal Simek break; 64784c7204bSMichal Simek } 64884c7204bSMichal Simek 6492882b39dSMichal Simek if (bootseq >= 0) { 6502882b39dSMichal Simek bootseq_len = snprintf(NULL, 0, "%i", bootseq); 6512882b39dSMichal Simek debug("Bootseq len: %x\n", bootseq_len); 6522882b39dSMichal Simek } 6532882b39dSMichal Simek 654b72894f1SMichal Simek /* 655b72894f1SMichal Simek * One terminating char + one byte for space between mode 656b72894f1SMichal Simek * and default boot_targets 657b72894f1SMichal Simek */ 65801c42d3dSSiva Durga Prasad Paladugu env_targets = env_get("boot_targets"); 6590478b0b9SMichal Simek if (env_targets) 6600478b0b9SMichal Simek env_targets_len = strlen(env_targets); 6610478b0b9SMichal Simek 6622882b39dSMichal Simek new_targets = calloc(1, strlen(mode) + env_targets_len + 2 + 6632882b39dSMichal Simek bootseq_len); 6641e3e68f1SMichal Simek if (!new_targets) 6651e3e68f1SMichal Simek return -ENOMEM; 6660478b0b9SMichal Simek 6672882b39dSMichal Simek if (bootseq >= 0) 6682882b39dSMichal Simek sprintf(new_targets, "%s%x %s", mode, bootseq, 6692882b39dSMichal Simek env_targets ? env_targets : ""); 6702882b39dSMichal Simek else 6710478b0b9SMichal Simek sprintf(new_targets, "%s %s", mode, 6720478b0b9SMichal Simek env_targets ? env_targets : ""); 673b72894f1SMichal Simek 674382bee57SSimon Glass env_set("boot_targets", new_targets); 675b72894f1SMichal Simek 676d348beaaSMichal Simek reset_reason(); 677d348beaaSMichal Simek 67884c7204bSMichal Simek return 0; 67984c7204bSMichal Simek } 6800bf3f9cbSMichal Simek #endif 68184696ff5SSiva Durga Prasad Paladugu 68284696ff5SSiva Durga Prasad Paladugu int checkboard(void) 68384696ff5SSiva Durga Prasad Paladugu { 6845af08556SMichal Simek puts("Board: Xilinx ZynqMP\n"); 68584696ff5SSiva Durga Prasad Paladugu return 0; 68684696ff5SSiva Durga Prasad Paladugu } 687