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> 236919b4bfSMichal Simek #include <i2c.h> 249feff385SMichal Simek #include <g_dnl.h> 2584c7204bSMichal Simek 2684c7204bSMichal Simek DECLARE_GLOBAL_DATA_PTR; 2784c7204bSMichal Simek 284490e013SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) 294490e013SMichal Simek static struct udevice *watchdog_dev; 304490e013SMichal Simek #endif 314490e013SMichal Simek 3247e60cbdSMichal Simek #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 3347e60cbdSMichal Simek !defined(CONFIG_SPL_BUILD) 3447e60cbdSMichal Simek static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC; 3547e60cbdSMichal Simek 3647e60cbdSMichal Simek static const struct { 378ebdf9efSMichal Simek u32 id; 38494fffe7SMichal Simek u32 ver; 3947e60cbdSMichal Simek char *name; 4083bf2ff0SSiva Durga Prasad Paladugu bool evexists; 4147e60cbdSMichal Simek } zynqmp_devices[] = { 4247e60cbdSMichal Simek { 4347e60cbdSMichal Simek .id = 0x10, 4447e60cbdSMichal Simek .name = "3eg", 4547e60cbdSMichal Simek }, 4647e60cbdSMichal Simek { 47494fffe7SMichal Simek .id = 0x10, 48494fffe7SMichal Simek .ver = 0x2c, 49494fffe7SMichal Simek .name = "3cg", 50494fffe7SMichal Simek }, 51494fffe7SMichal Simek { 5247e60cbdSMichal Simek .id = 0x11, 5347e60cbdSMichal Simek .name = "2eg", 5447e60cbdSMichal Simek }, 5547e60cbdSMichal Simek { 56494fffe7SMichal Simek .id = 0x11, 57494fffe7SMichal Simek .ver = 0x2c, 58494fffe7SMichal Simek .name = "2cg", 59494fffe7SMichal Simek }, 60494fffe7SMichal Simek { 6147e60cbdSMichal Simek .id = 0x20, 6247e60cbdSMichal Simek .name = "5ev", 6383bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 6447e60cbdSMichal Simek }, 6547e60cbdSMichal Simek { 66494fffe7SMichal Simek .id = 0x20, 67494fffe7SMichal Simek .ver = 0x100, 68494fffe7SMichal Simek .name = "5eg", 6983bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 70494fffe7SMichal Simek }, 71494fffe7SMichal Simek { 72494fffe7SMichal Simek .id = 0x20, 73494fffe7SMichal Simek .ver = 0x12c, 74494fffe7SMichal Simek .name = "5cg", 755473f245SSiva Durga Prasad Paladugu .evexists = 1, 76494fffe7SMichal Simek }, 77494fffe7SMichal Simek { 7847e60cbdSMichal Simek .id = 0x21, 7947e60cbdSMichal Simek .name = "4ev", 8083bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 8147e60cbdSMichal Simek }, 8247e60cbdSMichal Simek { 83494fffe7SMichal Simek .id = 0x21, 84494fffe7SMichal Simek .ver = 0x100, 85494fffe7SMichal Simek .name = "4eg", 8683bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 87494fffe7SMichal Simek }, 88494fffe7SMichal Simek { 89494fffe7SMichal Simek .id = 0x21, 90494fffe7SMichal Simek .ver = 0x12c, 91494fffe7SMichal Simek .name = "4cg", 925473f245SSiva Durga Prasad Paladugu .evexists = 1, 93494fffe7SMichal Simek }, 94494fffe7SMichal Simek { 9547e60cbdSMichal Simek .id = 0x30, 9647e60cbdSMichal Simek .name = "7ev", 9783bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 9847e60cbdSMichal Simek }, 9947e60cbdSMichal Simek { 100494fffe7SMichal Simek .id = 0x30, 101494fffe7SMichal Simek .ver = 0x100, 102494fffe7SMichal Simek .name = "7eg", 10383bf2ff0SSiva Durga Prasad Paladugu .evexists = 1, 104494fffe7SMichal Simek }, 105494fffe7SMichal Simek { 106494fffe7SMichal Simek .id = 0x30, 107494fffe7SMichal Simek .ver = 0x12c, 108494fffe7SMichal Simek .name = "7cg", 1095473f245SSiva Durga Prasad Paladugu .evexists = 1, 110494fffe7SMichal Simek }, 111494fffe7SMichal Simek { 11247e60cbdSMichal Simek .id = 0x38, 11347e60cbdSMichal Simek .name = "9eg", 11447e60cbdSMichal Simek }, 11547e60cbdSMichal Simek { 116494fffe7SMichal Simek .id = 0x38, 117494fffe7SMichal Simek .ver = 0x2c, 118494fffe7SMichal Simek .name = "9cg", 119494fffe7SMichal Simek }, 120494fffe7SMichal Simek { 12147e60cbdSMichal Simek .id = 0x39, 12247e60cbdSMichal Simek .name = "6eg", 12347e60cbdSMichal Simek }, 12447e60cbdSMichal Simek { 125494fffe7SMichal Simek .id = 0x39, 126494fffe7SMichal Simek .ver = 0x2c, 127494fffe7SMichal Simek .name = "6cg", 128494fffe7SMichal Simek }, 129494fffe7SMichal Simek { 13047e60cbdSMichal Simek .id = 0x40, 13147e60cbdSMichal Simek .name = "11eg", 13247e60cbdSMichal Simek }, 133494fffe7SMichal Simek { /* For testing purpose only */ 134494fffe7SMichal Simek .id = 0x50, 135494fffe7SMichal Simek .ver = 0x2c, 136494fffe7SMichal Simek .name = "15cg", 137494fffe7SMichal Simek }, 13847e60cbdSMichal Simek { 13947e60cbdSMichal Simek .id = 0x50, 14047e60cbdSMichal Simek .name = "15eg", 14147e60cbdSMichal Simek }, 14247e60cbdSMichal Simek { 14347e60cbdSMichal Simek .id = 0x58, 14447e60cbdSMichal Simek .name = "19eg", 14547e60cbdSMichal Simek }, 14647e60cbdSMichal Simek { 14747e60cbdSMichal Simek .id = 0x59, 14847e60cbdSMichal Simek .name = "17eg", 14947e60cbdSMichal Simek }, 150b030fedfSMichal Simek { 151b030fedfSMichal Simek .id = 0x61, 152b030fedfSMichal Simek .name = "21dr", 153b030fedfSMichal Simek }, 154b030fedfSMichal Simek { 155b030fedfSMichal Simek .id = 0x63, 156b030fedfSMichal Simek .name = "23dr", 157b030fedfSMichal Simek }, 158b030fedfSMichal Simek { 159b030fedfSMichal Simek .id = 0x65, 160b030fedfSMichal Simek .name = "25dr", 161b030fedfSMichal Simek }, 162b030fedfSMichal Simek { 163b030fedfSMichal Simek .id = 0x64, 164b030fedfSMichal Simek .name = "27dr", 165b030fedfSMichal Simek }, 166b030fedfSMichal Simek { 167b030fedfSMichal Simek .id = 0x60, 168b030fedfSMichal Simek .name = "28dr", 169b030fedfSMichal Simek }, 170b030fedfSMichal Simek { 171b030fedfSMichal Simek .id = 0x62, 172b030fedfSMichal Simek .name = "29dr", 173b030fedfSMichal Simek }, 17447e60cbdSMichal Simek }; 17574ba69dbSSiva Durga Prasad Paladugu #endif 17647e60cbdSMichal Simek 177f52bf5a3SSiva Durga Prasad Paladugu int chip_id(unsigned char id) 17847e60cbdSMichal Simek { 17947e60cbdSMichal Simek struct pt_regs regs; 18074ba69dbSSiva Durga Prasad Paladugu int val = -EINVAL; 18174ba69dbSSiva Durga Prasad Paladugu 18274ba69dbSSiva Durga Prasad Paladugu if (current_el() != 3) { 18347e60cbdSMichal Simek regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID; 18447e60cbdSMichal Simek regs.regs[1] = 0; 18547e60cbdSMichal Simek regs.regs[2] = 0; 18647e60cbdSMichal Simek regs.regs[3] = 0; 18747e60cbdSMichal Simek 18847e60cbdSMichal Simek smc_call(®s); 18947e60cbdSMichal Simek 1900cba6abbSSoren Brinkmann /* 1910cba6abbSSoren Brinkmann * SMC returns: 1920cba6abbSSoren Brinkmann * regs[0][31:0] = status of the operation 1930cba6abbSSoren Brinkmann * regs[0][63:32] = CSU.IDCODE register 1940cba6abbSSoren Brinkmann * regs[1][31:0] = CSU.version register 195494fffe7SMichal Simek * regs[1][63:32] = CSU.IDCODE2 register 1960cba6abbSSoren Brinkmann */ 197db3123b4SSiva Durga Prasad Paladugu switch (id) { 198db3123b4SSiva Durga Prasad Paladugu case IDCODE: 1990cba6abbSSoren Brinkmann regs.regs[0] = upper_32_bits(regs.regs[0]); 2000cba6abbSSoren Brinkmann regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 2010cba6abbSSoren Brinkmann ZYNQMP_CSU_IDCODE_SVD_MASK; 2020cba6abbSSoren Brinkmann regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 203db3123b4SSiva Durga Prasad Paladugu val = regs.regs[0]; 204db3123b4SSiva Durga Prasad Paladugu break; 205db3123b4SSiva Durga Prasad Paladugu case VERSION: 206db3123b4SSiva Durga Prasad Paladugu regs.regs[1] = lower_32_bits(regs.regs[1]); 207db3123b4SSiva Durga Prasad Paladugu regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK; 208db3123b4SSiva Durga Prasad Paladugu val = regs.regs[1]; 209db3123b4SSiva Durga Prasad Paladugu break; 210494fffe7SMichal Simek case IDCODE2: 211494fffe7SMichal Simek regs.regs[1] = lower_32_bits(regs.regs[1]); 212494fffe7SMichal Simek regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT; 213494fffe7SMichal Simek val = regs.regs[1]; 214494fffe7SMichal Simek break; 215db3123b4SSiva Durga Prasad Paladugu default: 216db3123b4SSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 217db3123b4SSiva Durga Prasad Paladugu } 21874ba69dbSSiva Durga Prasad Paladugu } else { 21974ba69dbSSiva Durga Prasad Paladugu switch (id) { 22074ba69dbSSiva Durga Prasad Paladugu case IDCODE: 22174ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_IDCODE_ADDR); 22274ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | 22374ba69dbSSiva Durga Prasad Paladugu ZYNQMP_CSU_IDCODE_SVD_MASK; 22474ba69dbSSiva Durga Prasad Paladugu val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; 22574ba69dbSSiva Durga Prasad Paladugu break; 22674ba69dbSSiva Durga Prasad Paladugu case VERSION: 22774ba69dbSSiva Durga Prasad Paladugu val = readl(ZYNQMP_CSU_VER_ADDR); 22874ba69dbSSiva Durga Prasad Paladugu val &= ZYNQMP_CSU_SILICON_VER_MASK; 22974ba69dbSSiva Durga Prasad Paladugu break; 23074ba69dbSSiva Durga Prasad Paladugu default: 23174ba69dbSSiva Durga Prasad Paladugu printf("%s, Invalid Req:0x%x\n", __func__, id); 23274ba69dbSSiva Durga Prasad Paladugu } 23374ba69dbSSiva Durga Prasad Paladugu } 2340cba6abbSSoren Brinkmann 235db3123b4SSiva Durga Prasad Paladugu return val; 23647e60cbdSMichal Simek } 23747e60cbdSMichal Simek 23883bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_VERSION_SIZE 9 23983bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_BIT 9 2405473f245SSiva Durga Prasad Paladugu #define ZYNQMP_IPDIS_VCU_BIT 8 24183bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) 24283bf2ff0SSiva Durga Prasad Paladugu #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) 2435473f245SSiva Durga Prasad Paladugu #define ZYNQMP_CSU_VCUDIS_VER_MASK ZYNQMP_CSU_VERSION_MASK & \ 2445473f245SSiva Durga Prasad Paladugu ~BIT(ZYNQMP_IPDIS_VCU_BIT) 2455473f245SSiva Durga Prasad Paladugu #define MAX_VARIANTS_EV 3 24683bf2ff0SSiva Durga Prasad Paladugu 24774ba69dbSSiva Durga Prasad Paladugu #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 24874ba69dbSSiva Durga Prasad Paladugu !defined(CONFIG_SPL_BUILD) 24947e60cbdSMichal Simek static char *zynqmp_get_silicon_idcode_name(void) 25047e60cbdSMichal Simek { 2515473f245SSiva Durga Prasad Paladugu u32 i, id, ver, j; 25283bf2ff0SSiva Durga Prasad Paladugu char *buf; 25383bf2ff0SSiva Durga Prasad Paladugu static char name[ZYNQMP_VERSION_SIZE]; 25447e60cbdSMichal Simek 255db3123b4SSiva Durga Prasad Paladugu id = chip_id(IDCODE); 256494fffe7SMichal Simek ver = chip_id(IDCODE2); 257494fffe7SMichal Simek 25847e60cbdSMichal Simek for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { 2595473f245SSiva Durga Prasad Paladugu if (zynqmp_devices[i].id == id) { 2605473f245SSiva Durga Prasad Paladugu if (zynqmp_devices[i].evexists && 2615473f245SSiva Durga Prasad Paladugu !(ver & ZYNQMP_PL_STATUS_MASK)) 2625473f245SSiva Durga Prasad Paladugu break; 2635473f245SSiva Durga Prasad Paladugu if (zynqmp_devices[i].ver == (ver & 2645473f245SSiva Durga Prasad Paladugu ZYNQMP_CSU_VERSION_MASK)) 26583bf2ff0SSiva Durga Prasad Paladugu break; 26647e60cbdSMichal Simek } 26783bf2ff0SSiva Durga Prasad Paladugu } 26883bf2ff0SSiva Durga Prasad Paladugu 26983bf2ff0SSiva Durga Prasad Paladugu if (i >= ARRAY_SIZE(zynqmp_devices)) 27047e60cbdSMichal Simek return "unknown"; 27183bf2ff0SSiva Durga Prasad Paladugu 2725473f245SSiva Durga Prasad Paladugu strncat(name, "zu", 2); 2735473f245SSiva Durga Prasad Paladugu if (!zynqmp_devices[i].evexists || 2745473f245SSiva Durga Prasad Paladugu (ver & ZYNQMP_PL_STATUS_MASK)) { 2755473f245SSiva Durga Prasad Paladugu strncat(name, zynqmp_devices[i].name, 2765473f245SSiva Durga Prasad Paladugu ZYNQMP_VERSION_SIZE - 3); 27783bf2ff0SSiva Durga Prasad Paladugu return name; 2785473f245SSiva Durga Prasad Paladugu } 27983bf2ff0SSiva Durga Prasad Paladugu 2805473f245SSiva Durga Prasad Paladugu /* 2815473f245SSiva Durga Prasad Paladugu * Here we are means, PL not powered up and ev variant 2825473f245SSiva Durga Prasad Paladugu * exists. So, we need to ignore VCU disable bit(8) in 2835473f245SSiva Durga Prasad Paladugu * version and findout if its CG or EG/EV variant. 2845473f245SSiva Durga Prasad Paladugu */ 2855473f245SSiva Durga Prasad Paladugu for (j = 0; j < MAX_VARIANTS_EV; j++, i++) { 2865473f245SSiva Durga Prasad Paladugu if ((zynqmp_devices[i].ver & ~BIT(ZYNQMP_IPDIS_VCU_BIT)) == 2875473f245SSiva Durga Prasad Paladugu (ver & ZYNQMP_CSU_VCUDIS_VER_MASK)) { 2885473f245SSiva Durga Prasad Paladugu strncat(name, zynqmp_devices[i].name, 2895473f245SSiva Durga Prasad Paladugu ZYNQMP_VERSION_SIZE - 3); 2905473f245SSiva Durga Prasad Paladugu break; 2915473f245SSiva Durga Prasad Paladugu } 2925473f245SSiva Durga Prasad Paladugu } 2935473f245SSiva Durga Prasad Paladugu 2945473f245SSiva Durga Prasad Paladugu if (j >= MAX_VARIANTS_EV) 2955473f245SSiva Durga Prasad Paladugu return "unknown"; 29683bf2ff0SSiva Durga Prasad Paladugu 29783bf2ff0SSiva Durga Prasad Paladugu if (strstr(name, "eg") || strstr(name, "ev")) { 29883bf2ff0SSiva Durga Prasad Paladugu buf = strstr(name, "e"); 29983bf2ff0SSiva Durga Prasad Paladugu *buf = '\0'; 30083bf2ff0SSiva Durga Prasad Paladugu } 30183bf2ff0SSiva Durga Prasad Paladugu 30283bf2ff0SSiva Durga Prasad Paladugu return name; 30347e60cbdSMichal Simek } 30447e60cbdSMichal Simek #endif 30547e60cbdSMichal Simek 306fb4000e8SMichal Simek int board_early_init_f(void) 307fb4000e8SMichal Simek { 308f32e79f1SMichal Simek int ret = 0; 309fb4000e8SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP) 310b94a8271SSiva Durga Prasad Paladugu u32 pm_api_version; 311b94a8271SSiva Durga Prasad Paladugu 312b94a8271SSiva Durga Prasad Paladugu pm_api_version = zynqmp_pmufw_version(); 313b94a8271SSiva Durga Prasad Paladugu printf("PMUFW:\tv%d.%d\n", 314b94a8271SSiva Durga Prasad Paladugu pm_api_version >> ZYNQMP_PM_VERSION_MAJOR_SHIFT, 315b94a8271SSiva Durga Prasad Paladugu pm_api_version & ZYNQMP_PM_VERSION_MINOR_MASK); 316b94a8271SSiva Durga Prasad Paladugu 317b94a8271SSiva Durga Prasad Paladugu if (pm_api_version < ZYNQMP_PM_VERSION) 318b94a8271SSiva Durga Prasad Paladugu panic("PMUFW version error. Expected: v%d.%d\n", 319b94a8271SSiva Durga Prasad Paladugu ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR); 320fb4000e8SMichal Simek #endif 32155de0929SMichal Simek 32288f05a92SMichal Simek #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) 323f32e79f1SMichal Simek ret = psu_init(); 32455de0929SMichal Simek #endif 32555de0929SMichal Simek 3264490e013SMichal Simek #if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD) 3274490e013SMichal Simek /* bss is not cleared at time when watchdog_reset() is called */ 3284490e013SMichal Simek watchdog_dev = NULL; 3294490e013SMichal Simek #endif 3304490e013SMichal Simek 331f32e79f1SMichal Simek return ret; 332fb4000e8SMichal Simek } 333fb4000e8SMichal Simek 33484c7204bSMichal Simek int board_init(void) 33584c7204bSMichal Simek { 336a0736efbSMichal Simek printf("EL Level:\tEL%d\n", current_el()); 337a0736efbSMichal Simek 33847e60cbdSMichal Simek #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ 33947e60cbdSMichal Simek !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \ 34047e60cbdSMichal Simek defined(CONFIG_SPL_BUILD)) 34147e60cbdSMichal Simek if (current_el() != 3) { 34283bf2ff0SSiva Durga Prasad Paladugu zynqmppl.name = zynqmp_get_silicon_idcode_name(); 34347e60cbdSMichal Simek printf("Chip ID:\t%s\n", zynqmppl.name); 34447e60cbdSMichal Simek fpga_init(); 34547e60cbdSMichal Simek fpga_add(fpga_xilinx, &zynqmppl); 34647e60cbdSMichal Simek } 34747e60cbdSMichal Simek #endif 34847e60cbdSMichal Simek 3494490e013SMichal Simek #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) 3501fbca0dbSMichal Simek if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) { 3511fbca0dbSMichal Simek debug("Watchdog: Not found by seq!\n"); 3524490e013SMichal Simek if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { 3534490e013SMichal Simek puts("Watchdog: Not found!\n"); 3541fbca0dbSMichal Simek return 0; 3551fbca0dbSMichal Simek } 3561fbca0dbSMichal Simek } 3571fbca0dbSMichal Simek 3584490e013SMichal Simek wdt_start(watchdog_dev, 0, 0); 3594490e013SMichal Simek puts("Watchdog: Started\n"); 3604490e013SMichal Simek #endif 3614490e013SMichal Simek 36284c7204bSMichal Simek return 0; 36384c7204bSMichal Simek } 36484c7204bSMichal Simek 3654490e013SMichal Simek #ifdef CONFIG_WATCHDOG 3664490e013SMichal Simek /* Called by macro WATCHDOG_RESET */ 3674490e013SMichal Simek void watchdog_reset(void) 3684490e013SMichal Simek { 3694490e013SMichal Simek # if !defined(CONFIG_SPL_BUILD) 3704490e013SMichal Simek static ulong next_reset; 3714490e013SMichal Simek ulong now; 3724490e013SMichal Simek 3734490e013SMichal Simek if (!watchdog_dev) 3744490e013SMichal Simek return; 3754490e013SMichal Simek 3764490e013SMichal Simek now = timer_get_us(); 3774490e013SMichal Simek 3784490e013SMichal Simek /* Do not reset the watchdog too often */ 3794490e013SMichal Simek if (now > next_reset) { 3804490e013SMichal Simek wdt_reset(watchdog_dev); 3814490e013SMichal Simek next_reset = now + 1000; 3824490e013SMichal Simek } 3834490e013SMichal Simek # endif 3844490e013SMichal Simek } 3854490e013SMichal Simek #endif 3864490e013SMichal Simek 38784c7204bSMichal Simek int board_early_init_r(void) 38884c7204bSMichal Simek { 38984c7204bSMichal Simek u32 val; 39084c7204bSMichal Simek 391ec60a279SSiva Durga Prasad Paladugu if (current_el() != 3) 392ec60a279SSiva Durga Prasad Paladugu return 0; 393ec60a279SSiva Durga Prasad Paladugu 39490a35db4SMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 39590a35db4SMichal Simek val &= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 39690a35db4SMichal Simek 397ec60a279SSiva Durga Prasad Paladugu if (!val) { 39884c7204bSMichal Simek val = readl(&crlapb_base->timestamp_ref_ctrl); 39984c7204bSMichal Simek val |= ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT; 40084c7204bSMichal Simek writel(val, &crlapb_base->timestamp_ref_ctrl); 40184c7204bSMichal Simek 4020785dfd8SMichal Simek /* Program freq register in System counter */ 4030785dfd8SMichal Simek writel(zynqmp_get_system_timer_freq(), 4040785dfd8SMichal Simek &iou_scntr_secure->base_frequency_id_register); 4050785dfd8SMichal Simek /* And enable system counter */ 4060785dfd8SMichal Simek writel(ZYNQMP_IOU_SCNTR_COUNTER_CONTROL_REGISTER_EN, 4070785dfd8SMichal Simek &iou_scntr_secure->counter_control_register); 4080785dfd8SMichal Simek } 40984c7204bSMichal Simek return 0; 41084c7204bSMichal Simek } 41184c7204bSMichal Simek 4126919b4bfSMichal Simek int zynq_board_read_rom_ethaddr(unsigned char *ethaddr) 4136919b4bfSMichal Simek { 4146919b4bfSMichal Simek #if defined(CONFIG_ZYNQ_GEM_EEPROM_ADDR) && \ 4156919b4bfSMichal Simek defined(CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET) && \ 4166919b4bfSMichal Simek defined(CONFIG_ZYNQ_EEPROM_BUS) 4176919b4bfSMichal Simek i2c_set_bus_num(CONFIG_ZYNQ_EEPROM_BUS); 4186919b4bfSMichal Simek 4196919b4bfSMichal Simek if (eeprom_read(CONFIG_ZYNQ_GEM_EEPROM_ADDR, 4206919b4bfSMichal Simek CONFIG_ZYNQ_GEM_I2C_MAC_OFFSET, 4216919b4bfSMichal Simek ethaddr, 6)) 4226919b4bfSMichal Simek printf("I2C EEPROM MAC address read failed\n"); 4236919b4bfSMichal Simek #endif 4246919b4bfSMichal Simek 4256919b4bfSMichal Simek return 0; 4266919b4bfSMichal Simek } 4276919b4bfSMichal Simek 42851916864SNitin Jain unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, 42951916864SNitin Jain char * const argv[]) 43051916864SNitin Jain { 43151916864SNitin Jain int ret = 0; 43251916864SNitin Jain 43351916864SNitin Jain if (current_el() > 1) { 43451916864SNitin Jain smp_kick_all_cpus(); 43551916864SNitin Jain dcache_disable(); 43651916864SNitin Jain armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry, 43751916864SNitin Jain ES_TO_AARCH64); 43851916864SNitin Jain } else { 43951916864SNitin Jain printf("FAIL: current EL is not above EL1\n"); 44051916864SNitin Jain ret = EINVAL; 44151916864SNitin Jain } 44251916864SNitin Jain return ret; 44351916864SNitin Jain } 44451916864SNitin Jain 4458d59d7f6SMichal Simek #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) 44676b00acaSSimon Glass int dram_init_banksize(void) 447361a8799STom Rini { 4480678941aSNitin Jain int ret; 4490678941aSNitin Jain 4500678941aSNitin Jain ret = fdtdec_setup_memory_banksize(); 4510678941aSNitin Jain if (ret) 4520678941aSNitin Jain return ret; 4530678941aSNitin Jain 4540678941aSNitin Jain mem_map_fill(); 4550678941aSNitin Jain 4560678941aSNitin Jain return 0; 4578d59d7f6SMichal Simek } 4588d59d7f6SMichal Simek 4598d59d7f6SMichal Simek int dram_init(void) 4608d59d7f6SMichal Simek { 46112308b12SSiva Durga Prasad Paladugu if (fdtdec_setup_mem_size_base() != 0) 462950f86caSNathan Rossi return -EINVAL; 4638d59d7f6SMichal Simek 4648d59d7f6SMichal Simek return 0; 4658d59d7f6SMichal Simek } 4668d59d7f6SMichal Simek #else 4670678941aSNitin Jain int dram_init_banksize(void) 4680678941aSNitin Jain { 4690678941aSNitin Jain #if defined(CONFIG_NR_DRAM_BANKS) 4700678941aSNitin Jain gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; 4710678941aSNitin Jain gd->bd->bi_dram[0].size = get_effective_memsize(); 4720678941aSNitin Jain #endif 4730678941aSNitin Jain 4740678941aSNitin Jain mem_map_fill(); 4750678941aSNitin Jain 4760678941aSNitin Jain return 0; 4770678941aSNitin Jain } 4780678941aSNitin Jain 47984c7204bSMichal Simek int dram_init(void) 48084c7204bSMichal Simek { 48161dc92a2SMichal Simek gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, 48261dc92a2SMichal Simek CONFIG_SYS_SDRAM_SIZE); 48384c7204bSMichal Simek 48484c7204bSMichal Simek return 0; 48584c7204bSMichal Simek } 4868d59d7f6SMichal Simek #endif 48784c7204bSMichal Simek 48884c7204bSMichal Simek void reset_cpu(ulong addr) 48984c7204bSMichal Simek { 49084c7204bSMichal Simek } 49184c7204bSMichal Simek 492d348beaaSMichal Simek static const struct { 493d348beaaSMichal Simek u32 bit; 494d348beaaSMichal Simek const char *name; 495d348beaaSMichal Simek } reset_reasons[] = { 496d348beaaSMichal Simek { RESET_REASON_DEBUG_SYS, "DEBUG" }, 497d348beaaSMichal Simek { RESET_REASON_SOFT, "SOFT" }, 498d348beaaSMichal Simek { RESET_REASON_SRST, "SRST" }, 499d348beaaSMichal Simek { RESET_REASON_PSONLY, "PS-ONLY" }, 500d348beaaSMichal Simek { RESET_REASON_PMU, "PMU" }, 501d348beaaSMichal Simek { RESET_REASON_INTERNAL, "INTERNAL" }, 502d348beaaSMichal Simek { RESET_REASON_EXTERNAL, "EXTERNAL" }, 503d348beaaSMichal Simek {} 504d348beaaSMichal Simek }; 505d348beaaSMichal Simek 506d348beaaSMichal Simek static u32 reset_reason(void) 507d348beaaSMichal Simek { 508d348beaaSMichal Simek u32 ret; 509d348beaaSMichal Simek int i; 510d348beaaSMichal Simek const char *reason = NULL; 511d348beaaSMichal Simek 512d348beaaSMichal Simek ret = readl(&crlapb_base->reset_reason); 513d348beaaSMichal Simek 514d348beaaSMichal Simek puts("Reset reason:\t"); 515d348beaaSMichal Simek 516d348beaaSMichal Simek for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) { 517d348beaaSMichal Simek if (ret & reset_reasons[i].bit) { 518d348beaaSMichal Simek reason = reset_reasons[i].name; 519d348beaaSMichal Simek printf("%s ", reset_reasons[i].name); 520d348beaaSMichal Simek break; 521d348beaaSMichal Simek } 522d348beaaSMichal Simek } 523d348beaaSMichal Simek 524d348beaaSMichal Simek puts("\n"); 525d348beaaSMichal Simek 526d348beaaSMichal Simek env_set("reset_reason", reason); 527d348beaaSMichal Simek 528d348beaaSMichal Simek writel(~0, &crlapb_base->reset_reason); 529d348beaaSMichal Simek 530d348beaaSMichal Simek return ret; 531d348beaaSMichal Simek } 532d348beaaSMichal Simek 53384c7204bSMichal Simek int board_late_init(void) 53484c7204bSMichal Simek { 53584c7204bSMichal Simek u32 reg = 0; 53684c7204bSMichal Simek u8 bootmode; 5372882b39dSMichal Simek struct udevice *dev; 5382882b39dSMichal Simek int bootseq = -1; 5392882b39dSMichal Simek int bootseq_len = 0; 5400478b0b9SMichal Simek int env_targets_len = 0; 541b72894f1SMichal Simek const char *mode; 542b72894f1SMichal Simek char *new_targets; 54301c42d3dSSiva Durga Prasad Paladugu char *env_targets; 544d1db89f4SSiva Durga Prasad Paladugu int ret; 545b72894f1SMichal Simek 546*e615f39eSMichal Simek #if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD) 547*e615f39eSMichal Simek usb_ether_init(); 548*e615f39eSMichal Simek #endif 549*e615f39eSMichal Simek 550b72894f1SMichal Simek if (!(gd->flags & GD_FLG_ENV_DEFAULT)) { 551b72894f1SMichal Simek debug("Saved variables - Skipping\n"); 552b72894f1SMichal Simek return 0; 553b72894f1SMichal Simek } 55484c7204bSMichal Simek 555d1db89f4SSiva Durga Prasad Paladugu ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); 556d1db89f4SSiva Durga Prasad Paladugu if (ret) 557d1db89f4SSiva Durga Prasad Paladugu return -EINVAL; 558d1db89f4SSiva Durga Prasad Paladugu 55947359a03SMichal Simek if (reg >> BOOT_MODE_ALT_SHIFT) 56047359a03SMichal Simek reg >>= BOOT_MODE_ALT_SHIFT; 56147359a03SMichal Simek 56284c7204bSMichal Simek bootmode = reg & BOOT_MODES_MASK; 56384c7204bSMichal Simek 564fb90917cSMichal Simek puts("Bootmode: "); 56584c7204bSMichal Simek switch (bootmode) { 566d58fc12eSMichal Simek case USB_MODE: 567d58fc12eSMichal Simek puts("USB_MODE\n"); 568d58fc12eSMichal Simek mode = "usb"; 56907656ba5SMichal Simek env_set("modeboot", "usb_dfu_spl"); 570d58fc12eSMichal Simek break; 5710a5bcc8cSSiva Durga Prasad Paladugu case JTAG_MODE: 572fb90917cSMichal Simek puts("JTAG_MODE\n"); 573b72894f1SMichal Simek mode = "pxe dhcp"; 57407656ba5SMichal Simek env_set("modeboot", "jtagboot"); 5750a5bcc8cSSiva Durga Prasad Paladugu break; 5760a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_24BIT: 5770a5bcc8cSSiva Durga Prasad Paladugu case QSPI_MODE_32BIT: 578b72894f1SMichal Simek mode = "qspi0"; 579fb90917cSMichal Simek puts("QSPI_MODE\n"); 58007656ba5SMichal Simek env_set("modeboot", "qspiboot"); 5810a5bcc8cSSiva Durga Prasad Paladugu break; 58239c56f55SMichal Simek case EMMC_MODE: 58378678feeSMichal Simek puts("EMMC_MODE\n"); 584b72894f1SMichal Simek mode = "mmc0"; 58507656ba5SMichal Simek env_set("modeboot", "emmcboot"); 58678678feeSMichal Simek break; 58778678feeSMichal Simek case SD_MODE: 588fb90917cSMichal Simek puts("SD_MODE\n"); 5892882b39dSMichal Simek if (uclass_get_device_by_name(UCLASS_MMC, 5902882b39dSMichal Simek "sdhci@ff160000", &dev)) { 5912882b39dSMichal Simek puts("Boot from SD0 but without SD0 enabled!\n"); 5922882b39dSMichal Simek return -1; 5932882b39dSMichal Simek } 5942882b39dSMichal Simek debug("mmc0 device found at %p, seq %d\n", dev, dev->seq); 5952882b39dSMichal Simek 5962882b39dSMichal Simek mode = "mmc"; 5972882b39dSMichal Simek bootseq = dev->seq; 59807656ba5SMichal Simek env_set("modeboot", "sdboot"); 59984c7204bSMichal Simek break; 600e1992276SSiva Durga Prasad Paladugu case SD1_LSHFT_MODE: 601e1992276SSiva Durga Prasad Paladugu puts("LVL_SHFT_"); 602e1992276SSiva Durga Prasad Paladugu /* fall through */ 603af813acdSMichal Simek case SD_MODE1: 604fb90917cSMichal Simek puts("SD_MODE1\n"); 6052882b39dSMichal Simek if (uclass_get_device_by_name(UCLASS_MMC, 6062882b39dSMichal Simek "sdhci@ff170000", &dev)) { 6072882b39dSMichal Simek puts("Boot from SD1 but without SD1 enabled!\n"); 6082882b39dSMichal Simek return -1; 6092882b39dSMichal Simek } 6102882b39dSMichal Simek debug("mmc1 device found at %p, seq %d\n", dev, dev->seq); 6112882b39dSMichal Simek 6122882b39dSMichal Simek mode = "mmc"; 6132882b39dSMichal Simek bootseq = dev->seq; 61407656ba5SMichal Simek env_set("modeboot", "sdboot"); 615af813acdSMichal Simek break; 616af813acdSMichal Simek case NAND_MODE: 617fb90917cSMichal Simek puts("NAND_MODE\n"); 618b72894f1SMichal Simek mode = "nand0"; 61907656ba5SMichal Simek env_set("modeboot", "nandboot"); 620af813acdSMichal Simek break; 62184c7204bSMichal Simek default: 622b72894f1SMichal Simek mode = ""; 62384c7204bSMichal Simek printf("Invalid Boot Mode:0x%x\n", bootmode); 62484c7204bSMichal Simek break; 62584c7204bSMichal Simek } 62684c7204bSMichal Simek 6272882b39dSMichal Simek if (bootseq >= 0) { 6282882b39dSMichal Simek bootseq_len = snprintf(NULL, 0, "%i", bootseq); 6292882b39dSMichal Simek debug("Bootseq len: %x\n", bootseq_len); 6302882b39dSMichal Simek } 6312882b39dSMichal Simek 632b72894f1SMichal Simek /* 633b72894f1SMichal Simek * One terminating char + one byte for space between mode 634b72894f1SMichal Simek * and default boot_targets 635b72894f1SMichal Simek */ 63601c42d3dSSiva Durga Prasad Paladugu env_targets = env_get("boot_targets"); 6370478b0b9SMichal Simek if (env_targets) 6380478b0b9SMichal Simek env_targets_len = strlen(env_targets); 6390478b0b9SMichal Simek 6402882b39dSMichal Simek new_targets = calloc(1, strlen(mode) + env_targets_len + 2 + 6412882b39dSMichal Simek bootseq_len); 6421e3e68f1SMichal Simek if (!new_targets) 6431e3e68f1SMichal Simek return -ENOMEM; 6440478b0b9SMichal Simek 6452882b39dSMichal Simek if (bootseq >= 0) 6462882b39dSMichal Simek sprintf(new_targets, "%s%x %s", mode, bootseq, 6472882b39dSMichal Simek env_targets ? env_targets : ""); 6482882b39dSMichal Simek else 6490478b0b9SMichal Simek sprintf(new_targets, "%s %s", mode, 6500478b0b9SMichal Simek env_targets ? env_targets : ""); 651b72894f1SMichal Simek 652382bee57SSimon Glass env_set("boot_targets", new_targets); 653b72894f1SMichal Simek 654d348beaaSMichal Simek reset_reason(); 655d348beaaSMichal Simek 65684c7204bSMichal Simek return 0; 65784c7204bSMichal Simek } 65884696ff5SSiva Durga Prasad Paladugu 65984696ff5SSiva Durga Prasad Paladugu int checkboard(void) 66084696ff5SSiva Durga Prasad Paladugu { 6615af08556SMichal Simek puts("Board: Xilinx ZynqMP\n"); 66284696ff5SSiva Durga Prasad Paladugu return 0; 66384696ff5SSiva Durga Prasad Paladugu } 664