diff options
author | Tom Rini <trini@konsulko.com> | 2016-09-22 11:36:23 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2016-09-22 11:36:23 -0400 |
commit | 58c8c0963b1c720802c46ac4288c897e5f9cd296 (patch) | |
tree | 08458bac1c2339713a4e0721ff857bcf123aecd6 | |
parent | a6c1309782e7a4a6b18e9514ca927487b5727232 (diff) | |
parent | e0027f089bb64f6b84742c580f966bf9c97c900e (diff) |
Merge branch 'master' of git://www.denx.de/git/u-boot-microblaze
23 files changed, 563 insertions, 31 deletions
diff --git a/arch/arm/cpu/armv8/zynqmp/Kconfig b/arch/arm/cpu/armv8/zynqmp/Kconfig index e7039919c7..1eedb39aa5 100644 --- a/arch/arm/cpu/armv8/zynqmp/Kconfig +++ b/arch/arm/cpu/armv8/zynqmp/Kconfig @@ -47,5 +47,53 @@ config ZYNQMP_USB config SYS_MALLOC_F_LEN default 0x600 +config SPL_ZYNQMP_ALT_BOOTMODE_ENABLED + bool "Overwrite SPL bootmode" + depends on SPL + help + Overwrite bootmode selected via boot mode pins to tell SPL what should + be the next boot device. + +config SPL_ZYNQMP_ALT_BOOTMODE + hex + default 0x0 if JTAG_MODE + default 0x1 if QSPI_MODE_24BIT + default 0x2 if QSPI_MODE_32BIT + default 0x3 if SD_MODE + default 0x4 if NAND_MODE + default 0x5 if SD_MODE1 + default 0x6 if EMMC_MODE + default 0x7 if USB_MODE + +choice + prompt "Boot mode" + depends on ZYNQMP_ALT_BOOTMODE_ENABLED + default JTAG + +config JTAG_MODE + bool "JTAG_MODE" + +config QSPI_MODE_24BIT + bool "QSPI_MODE_24BIT" + +config QSPI_MODE_32BIT + bool "QSPI_MODE_32BIT" + +config SD_MODE + bool "SD_MODE" + +config SD_MODE1 + bool "SD_MODE1" + +config NAND_MODE + bool "NAND_MODE" + +config EMMC_MODE + bool "EMMC_MODE" + +config USB_MODE + bool "USB" + +endchoice endif diff --git a/arch/arm/cpu/armv8/zynqmp/spl.c b/arch/arm/cpu/armv8/zynqmp/spl.c index 867d2b25a8..04e190537d 100644 --- a/arch/arm/cpu/armv8/zynqmp/spl.c +++ b/arch/arm/cpu/armv8/zynqmp/spl.c @@ -35,10 +35,29 @@ void board_init_f(ulong dummy) board_init_r(NULL, 0); } +static void ps_mode_reset(ulong mode) +{ + writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT, + &crlapb_base->boot_pin_ctrl); + udelay(5); + writel(mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT | + mode << ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT, + &crlapb_base->boot_pin_ctrl); +} + +/* + * Set default PS_MODE1 which is used for USB ULPI phy reset + * Also other resets can be connected to this certain pin + */ +#ifndef MODE_RESET +# define MODE_RESET PS_MODE1 +#endif + #ifdef CONFIG_SPL_BOARD_INIT void spl_board_init(void) { preloader_console_init(); + ps_mode_reset(MODE_RESET); board_init(); } #endif @@ -48,6 +67,13 @@ u32 spl_boot_device(void) u32 reg = 0; u8 bootmode; +#if defined(CONFIG_SPL_ZYNQMP_ALT_BOOTMODE_ENABLED) + /* Change default boot mode at run-time */ + writel(BOOT_MODE_USE_ALT | + CONFIG_SPL_ZYNQMP_ALT_BOOTMODE << BOOT_MODE_ALT_SHIFT, + &crlapb_base->boot_mode); +#endif + reg = readl(&crlapb_base->boot_mode); bootmode = reg & BOOT_MODES_MASK; @@ -60,6 +86,10 @@ u32 spl_boot_device(void) case SD_MODE1: return BOOT_DEVICE_MMC1; #endif +#ifdef CONFIG_SPL_DFU_SUPPORT + case USB_MODE: + return BOOT_DEVICE_DFU; +#endif default: printf("Invalid Boot Mode:0x%x\n", bootmode); break; diff --git a/arch/arm/include/asm/arch-zynqmp/hardware.h b/arch/arm/include/asm/arch-zynqmp/hardware.h index 35964d603b..456c1b0902 100644 --- a/arch/arm/include/asm/arch-zynqmp/hardware.h +++ b/arch/arm/include/asm/arch-zynqmp/hardware.h @@ -25,6 +25,13 @@ #define ZYNQMP_CRL_APB_BASEADDR 0xFF5E0000 #define ZYNQMP_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT 0x1000000 +#define ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_EN_SHIFT 0 +#define ZYNQMP_CRL_APB_BOOT_PIN_CTRL_OUT_VAL_SHIFT 8 + +#define PS_MODE0 BIT(0) +#define PS_MODE1 BIT(1) +#define PS_MODE2 BIT(2) +#define PS_MODE3 BIT(3) struct crlapb_regs { u32 reserved0[36]; @@ -35,7 +42,9 @@ struct crlapb_regs { u32 boot_mode; /* 0x200 */ u32 reserved3[14]; u32 rst_lpd_top; /* 0x23C */ - u32 reserved4[26]; + u32 reserved4[4]; + u32 boot_pin_ctrl; /* 0x250 */ + u32 reserved5[21]; }; #define crlapb_base ((struct crlapb_regs *)ZYNQMP_CRL_APB_BASEADDR) @@ -69,7 +78,10 @@ struct iou_scntr_secure { #define SD_MODE1 0x00000005 /* sd 1 */ #define NAND_MODE 0x00000004 #define EMMC_MODE 0x00000006 +#define USB_MODE 0x00000007 #define JTAG_MODE 0x00000000 +#define BOOT_MODE_USE_ALT 0x100 +#define BOOT_MODE_ALT_SHIFT 12 #define ZYNQMP_IOU_SLCR_BASEADDR 0xFF180000 diff --git a/arch/arm/include/asm/spl.h b/arch/arm/include/asm/spl.h index 19c38f4083..6f312d6652 100644 --- a/arch/arm/include/asm/spl.h +++ b/arch/arm/include/asm/spl.h @@ -28,6 +28,7 @@ enum { BOOT_DEVICE_SATA, BOOT_DEVICE_I2C, BOOT_DEVICE_BOARD, + BOOT_DEVICE_DFU, BOOT_DEVICE_NONE }; #endif diff --git a/board/xilinx/zynqmp/zynqmp.c b/board/xilinx/zynqmp/zynqmp.c index 0c5d997931..566b5e8d2a 100644 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@ -16,14 +16,114 @@ #include <asm/io.h> #include <usb.h> #include <dwc3-uboot.h> +#include <zynqmppl.h> #include <i2c.h> +#include <g_dnl.h> DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_FPGA) && defined(CONFIG_FPGA_ZYNQMPPL) && \ + !defined(CONFIG_SPL_BUILD) +static xilinx_desc zynqmppl = XILINX_ZYNQMP_DESC; + +static const struct { + uint32_t id; + char *name; +} zynqmp_devices[] = { + { + .id = 0x10, + .name = "3eg", + }, + { + .id = 0x11, + .name = "2eg", + }, + { + .id = 0x20, + .name = "5ev", + }, + { + .id = 0x21, + .name = "4ev", + }, + { + .id = 0x30, + .name = "7ev", + }, + { + .id = 0x38, + .name = "9eg", + }, + { + .id = 0x39, + .name = "6eg", + }, + { + .id = 0x40, + .name = "11eg", + }, + { + .id = 0x50, + .name = "15eg", + }, + { + .id = 0x58, + .name = "19eg", + }, + { + .id = 0x59, + .name = "17eg", + }, +}; + +static int chip_id(void) +{ + struct pt_regs regs; + regs.regs[0] = ZYNQMP_SIP_SVC_CSU_DMA_CHIPID; + regs.regs[1] = 0; + regs.regs[2] = 0; + regs.regs[3] = 0; + + smc_call(®s); + + return regs.regs[0]; +} + +static char *zynqmp_get_silicon_idcode_name(void) +{ + uint32_t i, id; + + id = chip_id(); + for (i = 0; i < ARRAY_SIZE(zynqmp_devices); i++) { + if (zynqmp_devices[i].id == id) + return zynqmp_devices[i].name; + } + return "unknown"; +} +#endif + +#define ZYNQMP_VERSION_SIZE 9 + int board_init(void) { printf("EL Level:\tEL%d\n", current_el()); +#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) { + static char version[ZYNQMP_VERSION_SIZE]; + + strncat(version, "xczu", ZYNQMP_VERSION_SIZE); + zynqmppl.name = strncat(version, + zynqmp_get_silicon_idcode_name(), + ZYNQMP_VERSION_SIZE); + printf("Chip ID:\t%s\n", zynqmppl.name); + fpga_init(); + fpga_add(fpga_xilinx, &zynqmppl); + } +#endif + return 0; } @@ -228,6 +328,10 @@ int board_late_init(void) puts("Bootmode: "); switch (bootmode) { + case USB_MODE: + puts("USB_MODE\n"); + mode = "usb"; + break; case JTAG_MODE: puts("JTAG_MODE\n"); mode = "pxe dhcp"; @@ -283,22 +387,38 @@ int checkboard(void) } #ifdef CONFIG_USB_DWC3 -static struct dwc3_device dwc3_device_data = { +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, }; -int usb_gadget_handle_interrupts(void) +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(0); + dwc3_uboot_handle_interrupt(index); return 0; } int board_usb_init(int index, enum usb_init_type init) { - return dwc3_uboot_init(&dwc3_device_data); + debug("%s: index %x\n", __func__, index); + + 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) diff --git a/configs/xilinx_zynqmp_ep_defconfig b/configs/xilinx_zynqmp_ep_defconfig index 196eb6974e..bd8b906a64 100644 --- a/configs/xilinx_zynqmp_ep_defconfig +++ b/configs/xilinx_zynqmp_ep_defconfig @@ -5,6 +5,7 @@ CONFIG_SYS_MALLOC_F_LEN=0x8000 CONFIG_ZYNQMP_USB=y CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-ep108" +CONFIG_AHCI=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y @@ -46,6 +47,8 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_BLK=y +CONFIG_FPGA_XILINX=y +CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y diff --git a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig index a3fb226e91..6afacd2d91 100644 --- a/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm015_dc1_defconfig @@ -38,6 +38,8 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_BLK=y +CONFIG_FPGA_XILINX=y +CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y diff --git a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig index aec4f9b3ee..4068c28818 100644 --- a/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm016_dc2_defconfig @@ -41,6 +41,8 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_BLK=y +CONFIG_FPGA_XILINX=y +CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y diff --git a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig index 0b2ebb1a54..c717f043bb 100644 --- a/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm018_dc4_defconfig @@ -1,5 +1,4 @@ CONFIG_ARM=y -CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_zc1751_xm018_dc4" CONFIG_ARCH_ZYNQMP=y CONFIG_SYS_MALLOC_F_LEN=0x8000 CONFIG_IDENT_STRING=" Xilinx ZynqMP ZC1751 xm018 dc4" @@ -34,6 +33,8 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_BLK=y +CONFIG_FPGA_XILINX=y +CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y diff --git a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig index f570b2aa42..1a27bd06ab 100644 --- a/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig +++ b/configs/xilinx_zynqmp_zc1751_xm019_dc5_defconfig @@ -33,6 +33,8 @@ CONFIG_OF_EMBED=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_BLK=y +CONFIG_FPGA_XILINX=y +CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_I2C=y CONFIG_SYS_I2C_CADENCE=y diff --git a/configs/xilinx_zynqmp_zcu102_defconfig b/configs/xilinx_zynqmp_zcu102_defconfig index 8fcb2fd3ee..90b5ff6c76 100644 --- a/configs/xilinx_zynqmp_zcu102_defconfig +++ b/configs/xilinx_zynqmp_zcu102_defconfig @@ -6,6 +6,7 @@ CONFIG_ZYNQMP_USB=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102" CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102" +CONFIG_AHCI=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y @@ -38,6 +39,8 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_BLK=y +CONFIG_FPGA_XILINX=y +CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_MMC=y CONFIG_DM_MMC_OPS=y diff --git a/configs/xilinx_zynqmp_zcu102_revB_defconfig b/configs/xilinx_zynqmp_zcu102_revB_defconfig index b7ba599a09..5a0d686931 100644 --- a/configs/xilinx_zynqmp_zcu102_revB_defconfig +++ b/configs/xilinx_zynqmp_zcu102_revB_defconfig @@ -6,6 +6,7 @@ CONFIG_ZYNQMP_USB=y CONFIG_IDENT_STRING=" Xilinx ZynqMP ZCU102" CONFIG_SYS_TEXT_BASE=0x8000000 CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102-revB" +CONFIG_AHCI=y CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_SPL_LOAD_FIT=y @@ -38,6 +39,8 @@ CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPL_DM=y CONFIG_SPL_DM_SEQ_ALIAS=y CONFIG_BLK=y +CONFIG_FPGA_XILINX=y +CONFIG_FPGA_ZYNQMPPL=y CONFIG_DM_GPIO=y CONFIG_DM_MMC=y CONFIG_DM_MMC_OPS=y diff --git a/drivers/Kconfig b/drivers/Kconfig index 4f84469955..4c555a0c1f 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -20,6 +20,8 @@ source "drivers/dfu/Kconfig" source "drivers/dma/Kconfig" +source "drivers/fpga/Kconfig" + source "drivers/gpio/Kconfig" source "drivers/hwmon/Kconfig" diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig new file mode 100644 index 0000000000..f3f6bf7f67 --- /dev/null +++ b/drivers/fpga/Kconfig @@ -0,0 +1,20 @@ +menu "FPGA support" + +config FPGA + bool + +config FPGA_XILINX + bool "Enable Xilinx FPGA drivers" + select FPGA + help + Enable Xilinx FPGA specific functions which includes bitstream + (in BIT format), fpga and device validation. + +config FPGA_ZYNQMPPL + bool "Enable Xilinx FPGA driver for ZynqMP" + depends on FPGA_XILINX + help + Enable FPGA driver for loading bitstream in BIT and BIN format + on Xilinx Zynq UltraScale+ (ZynqMP) device. + +endmenu diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index fec3fecbdf..777706f186 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_FPGA_SPARTAN2) += spartan2.o obj-$(CONFIG_FPGA_SPARTAN3) += spartan3.o obj-$(CONFIG_FPGA_VIRTEX2) += virtex2.o obj-$(CONFIG_FPGA_ZYNQPL) += zynqpl.o +obj-$(CONFIG_FPGA_ZYNQMPPL) += zynqmppl.o obj-$(CONFIG_FPGA_XILINX) += xilinx.o obj-$(CONFIG_FPGA_LATTICE) += ivm_core.o lattice.o ifdef CONFIG_FPGA_ALTERA diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index d459a2f7a5..2cd0104d8b 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -199,6 +199,9 @@ int xilinx_info(xilinx_desc *desc) case xilinx_zynq: printf("Zynq PL\n"); break; + case xilinx_zynqmp: + printf("ZynqMP PL\n"); + break; /* Add new family types here */ default: printf ("Unknown family type, %d\n", desc->family); @@ -227,6 +230,9 @@ int xilinx_info(xilinx_desc *desc) case devcfg: printf("Device configuration interface (Zynq)\n"); break; + case csu_dma: + printf("csu_dma configuration interface (ZynqMP)\n"); + break; /* Add new interface types here */ default: printf ("Unsupported interface type, %d\n", desc->iface); diff --git a/drivers/fpga/zynqmppl.c b/drivers/fpga/zynqmppl.c new file mode 100644 index 0000000000..23039c3eb2 --- /dev/null +++ b/drivers/fpga/zynqmppl.c @@ -0,0 +1,238 @@ +/* + * (C) Copyright 2015 - 2016, Xilinx, Inc, + * Michal Simek <michal.simek@xilinx.com> + * Siva Durga Prasad <siva.durga.paladugu@xilinx.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <console.h> +#include <common.h> +#include <zynqmppl.h> +#include <linux/sizes.h> + +#define DUMMY_WORD 0xffffffff + +/* Xilinx binary format header */ +static const u32 bin_format[] = { + DUMMY_WORD, /* Dummy words */ + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + DUMMY_WORD, + 0x000000bb, /* Sync word */ + 0x11220044, /* Sync word */ + DUMMY_WORD, + DUMMY_WORD, + 0xaa995566, /* Sync word */ +}; + +#define SWAP_NO 1 +#define SWAP_DONE 2 + +/* + * Load the whole word from unaligned buffer + * Keep in your mind that it is byte loading on little-endian system + */ +static u32 load_word(const void *buf, u32 swap) +{ + u32 word = 0; + u8 *bitc = (u8 *)buf; + int p; + + if (swap == SWAP_NO) { + for (p = 0; p < 4; p++) { + word <<= 8; + word |= bitc[p]; + } + } else { + for (p = 3; p >= 0; p--) { + word <<= 8; + word |= bitc[p]; + } + } + + return word; +} + +static u32 check_header(const void *buf) +{ + u32 i, pattern; + int swap = SWAP_NO; + u32 *test = (u32 *)buf; + + debug("%s: Let's check bitstream header\n", __func__); + + /* Checking that passing bin is not a bitstream */ + for (i = 0; i < ARRAY_SIZE(bin_format); i++) { + pattern = load_word(&test[i], swap); + + /* + * Bitstreams in binary format are swapped + * compare to regular bistream. + * Do not swap dummy word but if swap is done assume + * that parsing buffer is binary format + */ + if ((__swab32(pattern) != DUMMY_WORD) && + (__swab32(pattern) == bin_format[i])) { + swap = SWAP_DONE; + debug("%s: data swapped - let's swap\n", __func__); + } + + debug("%s: %d/%px: pattern %x/%x bin_format\n", __func__, i, + &test[i], pattern, bin_format[i]); + } + debug("%s: Found bitstream header at %px %s swapinng\n", __func__, + buf, swap == SWAP_NO ? "without" : "with"); + + return swap; +} + +static void *check_data(u8 *buf, size_t bsize, u32 *swap) +{ + u32 word, p = 0; /* possition */ + + /* Because buf doesn't need to be aligned let's read it by chars */ + for (p = 0; p < bsize; p++) { + word = load_word(&buf[p], SWAP_NO); + debug("%s: word %x %x/%px\n", __func__, word, p, &buf[p]); + + /* Find the first bitstream dummy word */ + if (word == DUMMY_WORD) { + debug("%s: Found dummy word at position %x/%px\n", + __func__, p, &buf[p]); + *swap = check_header(&buf[p]); + if (*swap) { + /* FIXME add full bitstream checking here */ + return &buf[p]; + } + } + /* Loop can be huge - support CTRL + C */ + if (ctrlc()) + return NULL; + } + return NULL; +} + +static ulong zynqmp_align_dma_buffer(u32 *buf, u32 len, u32 swap) +{ + u32 *new_buf; + u32 i; + + if ((ulong)buf != ALIGN((ulong)buf, ARCH_DMA_MINALIGN)) { + new_buf = (u32 *)ALIGN((ulong)buf, ARCH_DMA_MINALIGN); + + /* + * This might be dangerous but permits to flash if + * ARCH_DMA_MINALIGN is greater than header size + */ + if (new_buf > (u32 *)buf) { + debug("%s: Aligned buffer is after buffer start\n", + __func__); + new_buf -= ARCH_DMA_MINALIGN; + } + printf("%s: Align buffer at %px to %px(swap %d)\n", __func__, + buf, new_buf, swap); + + for (i = 0; i < (len/4); i++) + new_buf[i] = load_word(&buf[i], swap); + + buf = new_buf; + } else if (swap != SWAP_DONE) { + /* For bitstream which are aligned */ + u32 *new_buf = (u32 *)buf; + + printf("%s: Bitstream is not swapped(%d) - swap it\n", __func__, + swap); + + for (i = 0; i < (len/4); i++) + new_buf[i] = load_word(&buf[i], swap); + } + + return (ulong)buf; +} + +static int zynqmp_validate_bitstream(xilinx_desc *desc, const void *buf, + size_t bsize, u32 blocksize, u32 *swap) +{ + ulong *buf_start; + ulong diff; + + buf_start = check_data((u8 *)buf, blocksize, swap); + + if (!buf_start) + return FPGA_FAIL; + + /* Check if data is postpone from start */ + diff = (ulong)buf_start - (ulong)buf; + if (diff) { + printf("%s: Bitstream is not validated yet (diff %lx)\n", + __func__, diff); + return FPGA_FAIL; + } + + if ((ulong)buf < SZ_1M) { + printf("%s: Bitstream has to be placed up to 1MB (%px)\n", + __func__, buf); + return FPGA_FAIL; + } + + return 0; +} + +static int invoke_smc(ulong id, ulong reg0, ulong reg1, ulong reg2) +{ + struct pt_regs regs; + regs.regs[0] = id; + regs.regs[1] = reg0; + regs.regs[2] = reg1; + regs.regs[3] = reg2; + + smc_call(®s); + + return regs.regs[0]; +} + +static int zynqmp_load(xilinx_desc *desc, const void *buf, size_t bsize, + bitstream_type bstype) +{ + u32 swap; + ulong bin_buf, flags; + int ret; + + if (zynqmp_validate_bitstream(desc, buf, bsize, bsize, &swap)) + return FPGA_FAIL; + + bin_buf = zynqmp_align_dma_buffer((u32 *)buf, bsize, swap); + + debug("%s called!\n", __func__); + flush_dcache_range(bin_buf, bin_buf + bsize); + + if (bsize % 4) + bsize = bsize / 4 + 1; + else + bsize = bsize / 4; + + flags = (u32)bsize | ((u64)bstype << 32); + + ret = invoke_smc(ZYNQMP_SIP_SVC_PM_FPGA_LOAD, bin_buf, flags, 0); + if (ret) + debug("PL FPGA LOAD fail\n"); + + return ret; +} + +struct xilinx_fpga_op zynqmp_op = { + .load = zynqmp_load, +}; diff --git a/drivers/spi/zynq_spi.c b/drivers/spi/zynq_spi.c index 09ae1be7e9..7a176a2cd6 100644 --- a/drivers/spi/zynq_spi.c +++ b/drivers/spi/zynq_spi.c @@ -92,7 +92,8 @@ static void zynq_spi_init_hw(struct zynq_spi_priv *priv) u32 confr; /* Disable SPI */ - writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, ®s->enr); + confr = ZYNQ_SPI_ENR_SPI_EN_MASK; + writel(~confr, ®s->enr); /* Disable Interrupts */ writel(ZYNQ_SPI_IXR_ALL_MASK, ®s->idr); @@ -173,8 +174,10 @@ static int zynq_spi_release_bus(struct udevice *dev) struct udevice *bus = dev->parent; struct zynq_spi_priv *priv = dev_get_priv(bus); struct zynq_spi_regs *regs = priv->regs; + u32 confr; - writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, ®s->enr); + confr = ZYNQ_SPI_ENR_SPI_EN_MASK; + writel(~confr, ®s->enr); return 0; } diff --git a/include/configs/xilinx_zynqmp.h b/include/configs/xilinx_zynqmp.h index c43ea19807..5ed8beb9c2 100644 --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@ -75,7 +75,9 @@ /* Diff from config_distro_defaults.h */ #define CONFIG_SUPPORT_RAW_INITRD +#if !defined(CONFIG_SPL_BUILD) #define CONFIG_ENV_VARS_UBOOT_CONFIG +#endif #define CONFIG_AUTO_COMPLETE /* PXE */ @@ -108,7 +110,7 @@ #define CONFIG_SYS_LOAD_ADDR 0x8000000 #if defined(CONFIG_ZYNQMP_USB) -#define CONFIG_USB_MAX_CONTROLLER_COUNT 1 +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 #define CONFIG_USB_XHCI_ZYNQMP @@ -136,7 +138,6 @@ # define DFU_ALT_INFO #endif - #define CONFIG_BOARD_LATE_INIT /* Do not preserve environment */ @@ -185,7 +186,6 @@ #endif #ifdef CONFIG_SATA_CEVA -#define CONFIG_AHCI #define CONFIG_LIBATA #define CONFIG_SCSI_AHCI #define CONFIG_SCSI_AHCI_PLAT @@ -247,13 +247,24 @@ DFU_ALT_INFO #endif +/* SPL can't handle all huge variables - define just DFU */ +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_DFU_SUPPORT) +#undef CONFIG_EXTRA_ENV_SETTINGS +# define CONFIG_EXTRA_ENV_SETTINGS \ + "dfu_alt_info_ram=uboot.bin ram 0x8000000 0x1000000;" \ + "atf-uboot.ub ram 0x10000000 0x1000000;" \ + "Image ram 0x80000 0x3f80000;" \ + "system.dtb ram 0x4000000 0x100000\0" \ + "dfu_bufsiz=0x1000\0" +#endif + #define CONFIG_SPL_TEXT_BASE 0xfffc0000 #define CONFIG_SPL_STACK 0xfffffffc -#define CONFIG_SPL_MAX_SIZE 0x20000 +#define CONFIG_SPL_MAX_SIZE 0x40000 /* Just random location in OCM */ -#define CONFIG_SPL_BSS_START_ADDR 0x1000000 -#define CONFIG_SPL_BSS_MAX_SIZE 0x2000000 +#define CONFIG_SPL_BSS_START_ADDR 0x0 +#define CONFIG_SPL_BSS_MAX_SIZE 0x80000 #define CONFIG_SPL_FRAMEWORK #define CONFIG_SPL_BOARD_INIT @@ -265,7 +276,7 @@ #define CONFIG_SYS_SPL_ARGS_ADDR 0x8000000 /* ATF is my kernel image */ -#define CONFIG_SPL_FS_LOAD_KERNEL_NAME "atf.ub" +#define CONFIG_SPL_FS_LOAD_KERNEL_NAME "atf-uboot.ub" /* FIT load address for RAM boot */ #define CONFIG_SPL_LOAD_FIT_ADDRESS 0x10000000 @@ -279,4 +290,18 @@ # define CONFIG_SPL_FS_LOAD_PAYLOAD_NAME "u-boot.img" #endif +#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_DFU_SUPPORT) +# undef CONFIG_CMD_BOOTD +# define CONFIG_SPL_ENV_SUPPORT +# define CONFIG_SPL_HASH_SUPPORT +# define CONFIG_ENV_MAX_ENTRIES 10 + +# define CONFIG_SYS_SPL_MALLOC_START 0x20000000 +# define CONFIG_SYS_SPL_MALLOC_SIZE 0x10000000 + +#ifdef CONFIG_SPL_SYS_MALLOC_SIMPLE +# error "Disable CONFIG_SPL_SYS_MALLOC_SIMPLE. Full malloc needs to be used" +#endif +#endif + #endif /* __XILINX_ZYNQMP_H */ diff --git a/include/configs/xilinx_zynqmp_ep.h b/include/configs/xilinx_zynqmp_ep.h index 44434aab7b..8e4b96033b 100644 --- a/include/configs/xilinx_zynqmp_ep.h +++ b/include/configs/xilinx_zynqmp_ep.h @@ -16,7 +16,6 @@ #define CONFIG_ZYNQ_SDHCI_MAX_FREQ 52000000 #define CONFIG_ZYNQ_SDHCI_MIN_FREQ (CONFIG_ZYNQ_SDHCI_MAX_FREQ << 9) #define CONFIG_ZYNQ_EEPROM -#define CONFIG_AHCI #define CONFIG_SATA_CEVA #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \ ZYNQMP_USB1_XHCI_BASEADDR} diff --git a/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h b/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h deleted file mode 100644 index 4866b612d1..0000000000 --- a/include/configs/xilinx_zynqmp_zc1751_xm018_dc4.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Configuration for Xilinx ZynqMP zc1751 XM018 DC4 - * - * (C) Copyright 2015 Xilinx, Inc. - * Michal Simek <michal.simek@xilinx.com> - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#ifndef __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H -#define __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H - -#include <configs/xilinx_zynqmp.h> - -#endif /* __CONFIG_ZYNQMP_ZC1751_XM018_DC4_H */ diff --git a/include/xilinx.h b/include/xilinx.h index aebcb3bfdf..d2a2ea71e1 100644 --- a/include/xilinx.h +++ b/include/xilinx.h @@ -21,6 +21,7 @@ typedef enum { /* typedef xilinx_iface */ master_selectmap, /* master SelectMap (virtex2) */ slave_selectmap, /* slave SelectMap (virtex2) */ devcfg, /* devcfg interface (zynq) */ + csu_dma, /* csu_dma interface (zynqmp) */ max_xilinx_iface_type /* insert all new types before this */ } xilinx_iface; /* end, typedef xilinx_iface */ @@ -31,6 +32,7 @@ typedef enum { /* typedef xilinx_family */ xilinx_virtex2, /* Virtex2 Family */ xilinx_spartan3, /* Spartan-III Family */ xilinx_zynq, /* Zynq Family */ + xilinx_zynqmp, /* ZynqMP Family */ max_xilinx_type /* insert all new types before this */ } xilinx_family; /* end, typedef xilinx_family */ diff --git a/include/zynqmppl.h b/include/zynqmppl.h new file mode 100644 index 0000000000..542ace9a03 --- /dev/null +++ b/include/zynqmppl.h @@ -0,0 +1,24 @@ +/* + * (C) Copyright 2015 Xilinx, Inc, + * Michal Simek <michal.simek@xilinx.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ZYNQMPPL_H_ +#define _ZYNQMPPL_H_ + +#include <xilinx.h> + +#define ZYNQMP_SIP_SVC_CSU_DMA_CHIPID 0xC2000018 +#define ZYNQMP_SIP_SVC_PM_FPGA_LOAD 0xC2000016 +#define ZYNQMP_FPGA_OP_INIT (1 << 0) +#define ZYNQMP_FPGA_OP_LOAD (1 << 1) +#define ZYNQMP_FPGA_OP_DONE (1 << 2) + +extern struct xilinx_fpga_op zynqmp_op; + +#define XILINX_ZYNQMP_DESC \ +{ xilinx_zynqmp, csu_dma, 1, &zynqmp_op, 0, &zynqmp_op } + +#endif /* _ZYNQMPPL_H_ */ |