X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=board%2Fxilinx%2Fzynqmp%2Fzynqmp.c;h=b4e7301d50947cd8be8bc815c00ffbb0e5b28bd0;hb=7a1a01c6029039e4fa6aa185cdbbf9a357eecba7;hp=0c331e332230956f5e7386f3f3f9904e9f729b46;hpb=a69814c815b9a1a027f461ef26dbe7b2b8e258e4;p=platform%2Fkernel%2Fu-boot.git diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 0c331e3..b4e7301 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -5,7 +5,13 @@ */ #include +#include +#include +#include #include +#include +#include +#include #include #include #include @@ -15,14 +21,20 @@ #include #include #include +#include #include +#include #include #include #include #include #include +#include #include +#include +#include #include +#include "../common/board.h" #include "pm_cfg_obj.h" @@ -174,70 +186,17 @@ static const struct { .id = 0x66, .name = "39dr", }, + { + .id = 0x7b, + .name = "48dr", + }, + { + .id = 0x7e, + .name = "49dr", + }, }; #endif -int chip_id(unsigned char id) -{ - struct pt_regs regs; - int val = -EINVAL; - - if (current_el() != 3) { - regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID; - regs.regs[1] = 0; - regs.regs[2] = 0; - regs.regs[3] = 0; - - smc_call(®s); - - /* - * SMC returns: - * regs[0][31:0] = status of the operation - * regs[0][63:32] = CSU.IDCODE register - * regs[1][31:0] = CSU.version register - * regs[1][63:32] = CSU.IDCODE2 register - */ - switch (id) { - case IDCODE: - regs.regs[0] = upper_32_bits(regs.regs[0]); - regs.regs[0] &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | - ZYNQMP_CSU_IDCODE_SVD_MASK; - regs.regs[0] >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; - val = regs.regs[0]; - break; - case VERSION: - regs.regs[1] = lower_32_bits(regs.regs[1]); - regs.regs[1] &= ZYNQMP_CSU_SILICON_VER_MASK; - val = regs.regs[1]; - break; - case IDCODE2: - regs.regs[1] = lower_32_bits(regs.regs[1]); - regs.regs[1] >>= ZYNQMP_CSU_VERSION_EMPTY_SHIFT; - val = regs.regs[1]; - break; - default: - printf("%s, Invalid Req:0x%x\n", __func__, id); - } - } else { - switch (id) { - case IDCODE: - val = readl(ZYNQMP_CSU_IDCODE_ADDR); - val &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | - ZYNQMP_CSU_IDCODE_SVD_MASK; - val >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; - break; - case VERSION: - val = readl(ZYNQMP_CSU_VER_ADDR); - val &= ZYNQMP_CSU_SILICON_VER_MASK; - break; - default: - printf("%s, Invalid Req:0x%x\n", __func__, id); - } - } - - return val; -} - #define ZYNQMP_VERSION_SIZE 9 #define ZYNQMP_PL_STATUS_BIT 9 #define ZYNQMP_IPDIS_VCU_BIT 8 @@ -254,9 +213,28 @@ static char *zynqmp_get_silicon_idcode_name(void) u32 i, id, ver, j; char *buf; static char name[ZYNQMP_VERSION_SIZE]; + u32 ret_payload[PAYLOAD_ARG_CNT]; + + xilinx_pm_request(PM_GET_CHIPID, 0, 0, 0, 0, ret_payload); + + /* + * Firmware returns: + * payload[0][31:0] = status of the operation + * payload[1]] = IDCODE + * payload[2][19:0] = Version + * payload[2][28:20] = EXTENDED_IDCODE + * payload[2][29] = PL_INIT + */ + + /* Get IDCODE field */ + id = ret_payload[1]; + id &= ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK | ZYNQMP_CSU_IDCODE_SVD_MASK; + id >>= ZYNQMP_CSU_IDCODE_SVD_SHIFT; + + /* Shift silicon version info */ + ver = ret_payload[2] >> ZYNQMP_CSU_VERSION_EMPTY_SHIFT; - id = chip_id(IDCODE); - ver = chip_id(IDCODE2); + debug("%s, ID: 0x%0X, Ver: 0x%0X\r\n", __func__, id, ver); for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { if (zynqmp_devices[i].id == id) { @@ -308,29 +286,50 @@ static char *zynqmp_get_silicon_idcode_name(void) int board_early_init_f(void) { - int ret = 0; -#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_CLK_ZYNQMP) - u32 pm_api_version; +#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) + int ret; - 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); + ret = psu_init(); + if (ret) + return ret; - if (pm_api_version < ZYNQMP_PM_VERSION) - panic("PMUFW version error. Expected: v%d.%d\n", - ZYNQMP_PM_VERSION_MAJOR, ZYNQMP_PM_VERSION_MINOR); + /* Delay is required for clocks to be propagated */ + udelay(1000000); #endif -#if defined(CONFIG_ZYNQMP_PSU_INIT_ENABLED) - ret = psu_init(); +#ifdef CONFIG_DEBUG_UART + /* Uart debug for sure */ + debug_uart_init(); + puts("Debug uart enabled\n"); /* or printch() */ #endif - return ret; + return 0; +} + +static int multi_boot(void) +{ + u32 multiboot; + + multiboot = readl(&csu_base->multi_boot); + + printf("Multiboot:\t%d\n", multiboot); + + return 0; } +#define PS_SYSMON_ANALOG_BUS_VAL 0x3210 +#define PS_SYSMON_ANALOG_BUS_REG 0xFFA50914 + int board_init(void) { +#if defined(CONFIG_ZYNQMP_FIRMWARE) + struct udevice *dev; + + uclass_get_device_by_name(UCLASS_FIRMWARE, "zynqmp-power", &dev); + if (!dev) + panic("PMU Firmware device not found - Enable it"); +#endif + #if defined(CONFIG_SPL_BUILD) /* Check *at build time* if the filename is an non-empty string */ if (sizeof(CONFIG_ZYNQMP_SPL_PM_CFG_OBJ_FILE) > 1) @@ -340,17 +339,21 @@ int board_init(void) printf("EL Level:\tEL%d\n", current_el()); + /* Bug in ROM sets wrong value in this register */ + writel(PS_SYSMON_ANALOG_BUS_VAL, PS_SYSMON_ANALOG_BUS_REG); + #if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ !defined(CONFIG_SPL_BUILD) || (defined(CONFIG_SPL_FPGA_SUPPORT) && \ defined(CONFIG_SPL_BUILD)) - if (current_el() != 3) { - zynqmppl.name = zynqmp_get_silicon_idcode_name(); - printf("Chip ID:\t%s\n", zynqmppl.name); - fpga_init(); - fpga_add(fpga_xilinx, &zynqmppl); - } + zynqmppl.name = zynqmp_get_silicon_idcode_name(); + printf("Chip ID:\t%s\n", zynqmppl.name); + fpga_init(); + fpga_add(fpga_xilinx, &zynqmppl); #endif + if (current_el() == 3) + multi_boot(); + return 0; } @@ -380,7 +383,7 @@ int board_early_init_r(void) } unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, - char * const argv[]) + char *const argv[]) { int ret = 0; @@ -482,7 +485,7 @@ static int reset_reason(void) env_set("reset_reason", reason); - ret = zynqmp_mmio_write(~0, ~0, (ulong)&crlapb_base->reset_reason); + ret = zynqmp_mmio_write((ulong)&crlapb_base->reset_reason, ~0, ~0); if (ret) return -EINVAL; @@ -494,23 +497,30 @@ static int set_fdtfile(void) char *compatible, *fdtfile; const char *suffix = ".dtb"; const char *vendor = "xilinx/"; + int fdt_compat_len; if (env_get("fdtfile")) return 0; - compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", NULL); - if (compatible) { + compatible = (char *)fdt_getprop(gd->fdt_blob, 0, "compatible", + &fdt_compat_len); + if (compatible && fdt_compat_len) { + char *name; + debug("Compatible: %s\n", compatible); - /* Discard vendor prefix */ - strsep(&compatible, ","); + name = strchr(compatible, ','); + if (!name) + return -EINVAL; + + name++; - fdtfile = calloc(1, strlen(vendor) + strlen(compatible) + + fdtfile = calloc(1, strlen(vendor) + strlen(name) + strlen(suffix) + 1); if (!fdtfile) return -ENOMEM; - sprintf(fdtfile, "%s%s%s", vendor, compatible, suffix); + sprintf(fdtfile, "%s%s%s", vendor, name, suffix); env_set("fdtfile", fdtfile); free(fdtfile); @@ -519,9 +529,26 @@ static int set_fdtfile(void) return 0; } -int board_late_init(void) +static u8 zynqmp_get_bootmode(void) { + u8 bootmode; u32 reg = 0; + int ret; + + ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); + if (ret) + return -EINVAL; + + if (reg >> BOOT_MODE_ALT_SHIFT) + reg >>= BOOT_MODE_ALT_SHIFT; + + bootmode = reg & BOOT_MODES_MASK; + + return bootmode; +} + +int board_late_init(void) +{ u8 bootmode; struct udevice *dev; int bootseq = -1; @@ -531,7 +558,6 @@ int board_late_init(void) char *new_targets; char *env_targets; int ret; - ulong initrd_hi; #if defined(CONFIG_USB_ETHER) && !defined(CONFIG_USB_GADGET_DOWNLOAD) usb_ether_init(); @@ -542,18 +568,14 @@ int board_late_init(void) return 0; } + if (!CONFIG_IS_ENABLED(ENV_VARS_UBOOT_RUNTIME_CONFIG)) + return 0; + ret = set_fdtfile(); if (ret) return ret; - ret = zynqmp_mmio_read((ulong)&crlapb_base->boot_mode, ®); - if (ret) - return -EINVAL; - - if (reg >> BOOT_MODE_ALT_SHIFT) - reg >>= BOOT_MODE_ALT_SHIFT; - - bootmode = reg & BOOT_MODES_MASK; + bootmode = zynqmp_get_bootmode(); puts("Bootmode: "); switch (bootmode) { @@ -564,7 +586,7 @@ int board_late_init(void) break; case JTAG_MODE: puts("JTAG_MODE\n"); - mode = "pxe dhcp"; + mode = "jtag pxe dhcp"; env_set("modeboot", "jtagboot"); break; case QSPI_MODE_24BIT: @@ -575,8 +597,17 @@ int board_late_init(void) break; case EMMC_MODE: puts("EMMC_MODE\n"); - mode = "mmc0"; - env_set("modeboot", "emmcboot"); + if (uclass_get_device_by_name(UCLASS_MMC, + "mmc@ff160000", &dev) && + uclass_get_device_by_name(UCLASS_MMC, + "sdhci@ff160000", &dev)) { + puts("Boot from EMMC but without SD0 enabled!\n"); + return -1; + } + debug("mmc0 device found at %p, seq %d\n", dev, dev->seq); + + mode = "mmc"; + bootseq = dev->seq; break; case SD_MODE: puts("SD_MODE\n"); @@ -649,13 +680,9 @@ int board_late_init(void) env_set("boot_targets", new_targets); - initrd_hi = gd->start_addr_sp - CONFIG_STACK_SIZE; - initrd_hi = round_down(initrd_hi, SZ_16M); - env_set_addr("initrd_high", (void *)initrd_hi); - reset_reason(); - return 0; + return board_late_init_xilinx(); } #endif