X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=board%2Fxilinx%2Fzynqmp%2Fzynqmp.c;h=168cf5c14b4565d068803e668f92bb74e6ce86dd;hb=5473f245d0a884ffd1a7f353b86d5d11e01d3ebd;hp=0d1bd5412b166e37f04f7cf67197e668def35edb;hpb=f7c9e76fb85369aa6a347201b04ad8c676c42665;p=oweals%2Fu-boot.git diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 0d1bd5412b..168cf5c14b 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * (C) Copyright 2014 - 2015 Xilinx, Inc. * Michal Simek - * - * SPDX-License-Identifier: GPL-2.0+ */ #include @@ -10,11 +9,14 @@ #include #include #include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -23,6 +25,10 @@ DECLARE_GLOBAL_DATA_PTR; +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) +static struct udevice *watchdog_dev; +#endif + #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ !defined(CONFIG_SPL_BUILD) static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC; @@ -66,6 +72,7 @@ static const struct { .id = 0x20, .ver = 0x12c, .name = "5cg", + .evexists = 1, }, { .id = 0x21, @@ -82,6 +89,7 @@ static const struct { .id = 0x21, .ver = 0x12c, .name = "4cg", + .evexists = 1, }, { .id = 0x30, @@ -98,6 +106,7 @@ static const struct { .id = 0x30, .ver = 0x12c, .name = "7cg", + .evexists = 1, }, { .id = 0x38, @@ -228,14 +237,18 @@ int chip_id(unsigned char id) #define ZYNQMP_VERSION_SIZE 9 #define ZYNQMP_PL_STATUS_BIT 9 +#define ZYNQMP_IPDIS_VCU_BIT 8 #define ZYNQMP_PL_STATUS_MASK BIT(ZYNQMP_PL_STATUS_BIT) #define ZYNQMP_CSU_VERSION_MASK ~(ZYNQMP_PL_STATUS_MASK) +#define ZYNQMP_CSU_VCUDIS_VER_MASK ZYNQMP_CSU_VERSION_MASK & \ + ~BIT(ZYNQMP_IPDIS_VCU_BIT) +#define MAX_VARIANTS_EV 3 #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ !defined(CONFIG_SPL_BUILD) static char *zynqmp_get_silicon_idcode_name(void) { - u32 i, id, ver; + u32 i, id, ver, j; char *buf; static char name[ZYNQMP_VERSION_SIZE]; @@ -243,24 +256,43 @@ static char *zynqmp_get_silicon_idcode_name(void) ver = chip_id(IDCODE2); for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { - if ((zynqmp_devices[i].id == id) && - (zynqmp_devices[i].ver == (ver & - ZYNQMP_CSU_VERSION_MASK))) { - strncat(name, "zu", 2); - strncat(name, zynqmp_devices[i].name, - ZYNQMP_VERSION_SIZE - 3); - break; + if (zynqmp_devices[i].id == id) { + if (zynqmp_devices[i].evexists && + !(ver & ZYNQMP_PL_STATUS_MASK)) + break; + if (zynqmp_devices[i].ver == (ver & + ZYNQMP_CSU_VERSION_MASK)) + break; } } if (i >= ARRAY_SIZE(zynqmp_devices)) return "unknown"; - if (!zynqmp_devices[i].evexists) + strncat(name, "zu", 2); + if (!zynqmp_devices[i].evexists || + (ver & ZYNQMP_PL_STATUS_MASK)) { + strncat(name, zynqmp_devices[i].name, + ZYNQMP_VERSION_SIZE - 3); return name; + } - if (ver & ZYNQMP_PL_STATUS_MASK) - return name; + /* + * Here we are means, PL not powered up and ev variant + * exists. So, we need to ignore VCU disable bit(8) in + * version and findout if its CG or EG/EV variant. + */ + for (j = 0; j < MAX_VARIANTS_EV; j++, i++) { + if ((zynqmp_devices[i].ver & ~BIT(ZYNQMP_IPDIS_VCU_BIT)) == + (ver & ZYNQMP_CSU_VCUDIS_VER_MASK)) { + strncat(name, zynqmp_devices[i].name, + ZYNQMP_VERSION_SIZE - 3); + break; + } + } + + if (j >= MAX_VARIANTS_EV) + return "unknown"; if (strstr(name, "eg") || strstr(name, "ev")) { buf = strstr(name, "e"); @@ -275,13 +307,27 @@ int board_early_init_f(void) { int ret = 0; #if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP) - zynqmp_pmufw_version(); + u32 pm_api_version; + + pm_api_version = zynqmp_pmufw_version(); + printf("PMUFW:\tv%d.%d\n", + pm_api_version >> ZYNQMP_PM_VERSION_MAJOR_SHIFT, + pm_api_version & ZYNQMP_PM_VERSION_MINOR_MASK); + + if (pm_api_version < ZYNQMP_PM_VERSION) + panic("PMUFW version error. Expected: v%d.%d\n", + ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR); #endif #if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) ret = psu_init(); #endif +#if defined(CONFIG_WDT) && !defined(CONFIG_SPL_BUILD) + /* bss is not cleared at time when watchdog_reset() is called */ + watchdog_dev = NULL; +#endif + return ret; } @@ -300,9 +346,44 @@ int board_init(void) } #endif +#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT) + if (uclass_get_device_by_seq(UCLASS_WDT, 0, &watchdog_dev)) { + debug("Watchdog: Not found by seq!\n"); + if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { + puts("Watchdog: Not found!\n"); + return 0; + } + } + + wdt_start(watchdog_dev, 0, 0); + puts("Watchdog: Started\n"); +#endif + return 0; } +#ifdef CONFIG_WATCHDOG +/* Called by macro WATCHDOG_RESET */ +void watchdog_reset(void) +{ +# if !defined(CONFIG_SPL_BUILD) + static ulong next_reset; + ulong now; + + if (!watchdog_dev) + return; + + now = timer_get_us(); + + /* Do not reset the watchdog too often */ + if (now > next_reset) { + wdt_reset(watchdog_dev); + next_reset = now + 1000; + } +# endif +} +#endif + int board_early_init_r(void) { u32 val; @@ -364,20 +445,41 @@ unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, #if !defined(CONFIG_SYS_SDRAM_BASE) && !defined(CONFIG_SYS_SDRAM_SIZE) int dram_init_banksize(void) { - return fdtdec_setup_memory_banksize(); + int ret; + + ret = fdtdec_setup_memory_banksize(); + if (ret) + return ret; + + mem_map_fill(); + + return 0; } int dram_init(void) { - if (fdtdec_setup_memory_size() != 0) + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; return 0; } #else +int dram_init_banksize(void) +{ +#if defined(CONFIG_NR_DRAM_BANKS) + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + gd->bd->bi_dram[0].size = get_effective_memsize(); +#endif + + mem_map_fill(); + + return 0; +} + int dram_init(void) { - gd->ram_size = CONFIG_SYS_SDRAM_SIZE; + gd->ram_size = get_ram_size((void *)CONFIG_SYS_SDRAM_BASE, + CONFIG_SYS_SDRAM_SIZE); return 0; } @@ -387,10 +489,55 @@ void reset_cpu(ulong addr) { } +static const struct { + u32 bit; + const char *name; +} reset_reasons[] = { + { RESET_REASON_DEBUG_SYS, "DEBUG" }, + { RESET_REASON_SOFT, "SOFT" }, + { RESET_REASON_SRST, "SRST" }, + { RESET_REASON_PSONLY, "PS-ONLY" }, + { RESET_REASON_PMU, "PMU" }, + { RESET_REASON_INTERNAL, "INTERNAL" }, + { RESET_REASON_EXTERNAL, "EXTERNAL" }, + {} +}; + +static u32 reset_reason(void) +{ + u32 ret; + int i; + const char *reason = NULL; + + ret = readl(&crlapb_base->reset_reason); + + puts("Reset reason:\t"); + + for (i = 0; i < ARRAY_SIZE(reset_reasons); i++) { + if (ret & reset_reasons[i].bit) { + reason = reset_reasons[i].name; + printf("%s ", reset_reasons[i].name); + break; + } + } + + puts("\n"); + + env_set("reset_reason", reason); + + writel(~0, &crlapb_base->reset_reason); + + return ret; +} + int board_late_init(void) { u32 reg = 0; u8 bootmode; + struct udevice *dev; + int bootseq = -1; + int bootseq_len = 0; + int env_targets_len = 0; const char *mode; char *new_targets; char *env_targets; @@ -435,7 +582,15 @@ int board_late_init(void) break; case SD_MODE: puts("SD_MODE\n"); - mode = "mmc0"; + if (uclass_get_device_by_name(UCLASS_MMC, + "sdhci@ff160000", &dev)) { + puts("Boot from SD0 but without SD0 enabled!\n"); + return -1; + } + debug("mmc0 device found at %p, seq %d\n", dev, dev->seq); + + mode = "mmc"; + bootseq = dev->seq; env_set("modeboot", "sdboot"); break; case SD1_LSHFT_MODE: @@ -443,12 +598,15 @@ int board_late_init(void) /* fall through */ case SD_MODE1: puts("SD_MODE1\n"); -#if defined(CONFIG_ZYNQ_SDHCI0) && defined(CONFIG_ZYNQ_SDHCI1) - mode = "mmc1"; - env_set("sdbootdev", "1"); -#else - mode = "mmc0"; -#endif + if (uclass_get_device_by_name(UCLASS_MMC, + "sdhci@ff170000", &dev)) { + puts("Boot from SD1 but without SD1 enabled!\n"); + return -1; + } + debug("mmc1 device found at %p, seq %d\n", dev, dev->seq); + + mode = "mmc"; + bootseq = dev->seq; env_set("modeboot", "sdboot"); break; case NAND_MODE: @@ -462,73 +620,40 @@ int board_late_init(void) break; } + if (bootseq >= 0) { + bootseq_len = snprintf(NULL, 0, "%i", bootseq); + debug("Bootseq len: %x\n", bootseq_len); + } + /* * One terminating char + one byte for space between mode * and default boot_targets */ env_targets = env_get("boot_targets"); - if (env_targets) { - new_targets = calloc(1, strlen(mode) + - strlen(env_targets) + 2); - sprintf(new_targets, "%s %s", mode, env_targets); - } else { - new_targets = calloc(1, strlen(mode) + 2); - sprintf(new_targets, "%s", mode); - } + if (env_targets) + env_targets_len = strlen(env_targets); - env_set("boot_targets", new_targets); + new_targets = calloc(1, strlen(mode) + env_targets_len + 2 + + bootseq_len); + if (!new_targets) + return -ENOMEM; - return 0; -} + if (bootseq >= 0) + sprintf(new_targets, "%s%x %s", mode, bootseq, + env_targets ? env_targets : ""); + else + sprintf(new_targets, "%s %s", mode, + env_targets ? env_targets : ""); -int checkboard(void) -{ - puts("Board: Xilinx ZynqMP\n"); - return 0; -} + env_set("boot_targets", new_targets); -#ifdef CONFIG_USB_DWC3 -static struct dwc3_device dwc3_device_data0 = { - .maximum_speed = USB_SPEED_HIGH, - .base = ZYNQMP_USB0_XHCI_BASEADDR, - .dr_mode = USB_DR_MODE_PERIPHERAL, - .index = 0, -}; + reset_reason(); -static struct dwc3_device dwc3_device_data1 = { - .maximum_speed = USB_SPEED_HIGH, - .base = ZYNQMP_USB1_XHCI_BASEADDR, - .dr_mode = USB_DR_MODE_PERIPHERAL, - .index = 1, -}; - -int usb_gadget_handle_interrupts(int index) -{ - dwc3_uboot_handle_interrupt(index); return 0; } -int board_usb_init(int index, enum usb_init_type init) -{ - debug("%s: index %x\n", __func__, index); - -#if defined(CONFIG_USB_GADGET_DOWNLOAD) - g_dnl_set_serialnumber(CONFIG_SYS_CONFIG_NAME); -#endif - - switch (index) { - case 0: - return dwc3_uboot_init(&dwc3_device_data0); - case 1: - return dwc3_uboot_init(&dwc3_device_data1); - }; - - return -1; -} - -int board_usb_cleanup(int index, enum usb_init_type init) +int checkboard(void) { - dwc3_uboot_exit(index); + puts("Board: Xilinx ZynqMP\n"); return 0; } -#endif