From: Michal Simek Date: Wed, 13 Jan 2016 12:25:03 +0000 (+0100) Subject: Merge tag 'v2016.01' into xilinx/master X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3ad1b54b23921ba0f2961051cbcd0bd3b3162440;p=thirdparty%2Fu-boot.git Merge tag 'v2016.01' into xilinx/master Prepare v2016.01 Various QSPI fixes from Siva were applied: spi_flash: Add support for device with Quad IO support zynq_qspi: Update parent priv data during pre probe of qspi zynq-common: Add missing dual flash support in zynq spi: spi_flash: Add support for generic qspi zynqmp_qspi: Update parent priv data during pre probe of qspi spi: spi_flash: Add 4-byte support for spi flash spi: spi_flash: Correct flash size calculation spi: spi_flash: Add support for Dual stacked mode Add ifdef around CONFIG_FEC_MXC to remove compilation warnings. Remove qspi flash enabling via defconfig. Do it later. Signed-off-by: Michal Simek --- 3ad1b54b23921ba0f2961051cbcd0bd3b3162440 diff --cc Makefile index b2c70d4393f,100de92eab5..100de92eab5 mode 100755,100644..100755 --- a/Makefile +++ b/Makefile diff --cc arch/arm/Kconfig index b5229aefec0,9bd6cf1d807..b49dfe99767 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@@ -555,10 -565,10 +565,13 @@@ config ARCH_ZYNQM bool "Support Xilinx ZynqMP Platform" select ARM64 select DM - select OF_CONTROL + select DM_SPI + select DM_SPI_FLASH + select DM_ETH + select DM_MMC + select DM_SERIAL + select OF_CONTROL + select SPL_DISABLE_OF_CONTROL config TEGRA bool "NVIDIA Tegra" diff --cc arch/arm/dts/Makefile index 1d73a8ec11d,0bcd3163756..fde153eacea --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@@ -67,14 -70,10 +77,16 @@@ dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.d zynq-zc770-xm011.dtb \ zynq-zc770-xm012.dtb \ zynq-zc770-xm013.dtb - dtb-$(CONFIG_ARCH_ZYNQMP) += zynqmp-ep108.dtb \ + dtb-$(CONFIG_ARCH_ZYNQMP) += \ - zynqmp-ep108.dtb ++ zynqmp-ep108.dtb \ + zynqmp-zcu102.dtb \ + zynqmp-zc1751-xm015-dc1.dtb \ + zynqmp-zc1751-xm016-dc2.dtb \ + zynqmp-zc1751-xm019-dc5.dtb \ + zynqmp-mini-qspi.dtb \ + zynqmp-mini-nand.dtb dtb-$(CONFIG_AM33XX) += am335x-boneblack.dtb am335x-evm.dtb + dtb-$(CONFIG_AM43XX) += am437x-gp-evm.dtb am437x-sk-evm.dtb dtb-$(CONFIG_ARCH_SOCFPGA) += \ socfpga_arria5_socdk.dtb \ diff --cc arch/arm/dts/zynq-zc702.dts index accde79e6b2,528cd27796c..40b085c9c8c --- a/arch/arm/dts/zynq-zc702.dts +++ b/arch/arm/dts/zynq-zc702.dts @@@ -391,42 -370,8 +391,43 @@@ }; }; +&qspi { + status = "okay"; + is-dual = <0>; + num-cs = <1>; + flash@0 { + compatible = "n25q128a11"; + reg = <0x0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <50000000>; + #address-cells = <1>; + #size-cells = <1>; + partition@qspi-fsbl-uboot { + label = "qspi-fsbl-uboot"; + reg = <0x0 0x100000>; + }; + partition@qspi-linux { + label = "qspi-linux"; + reg = <0x100000 0x500000>; + }; + partition@qspi-device-tree { + label = "qspi-device-tree"; + reg = <0x600000 0x20000>; + }; + partition@qspi-rootfs { + label = "qspi-rootfs"; + reg = <0x620000 0x5E0000>; + }; + partition@qspi-bitstream { + label = "qspi-bitstream"; + reg = <0xC00000 0x400000>; + }; + }; +}; + &sdhci0 { + u-boot,dm-pre-reloc; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdhci0_default>; diff --cc arch/arm/dts/zynq-zc706.dts index 5bcbc8cb1f7,1ba3a1c6e8d..119c1cb7a59 --- a/arch/arm/dts/zynq-zc706.dts +++ b/arch/arm/dts/zynq-zc706.dts @@@ -291,42 -291,8 +291,43 @@@ }; }; +&qspi { + status = "okay"; + is-dual = <1>; + num-cs = <1>; + flash@0 { + compatible = "n25q128a11"; + reg = <0x0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <50000000>; + #address-cells = <1>; + #size-cells = <1>; + partition@qspi-fsbl-uboot { + label = "qspi-fsbl-uboot"; + reg = <0x0 0x100000>; + }; + partition@qspi-linux { + label = "qspi-linux"; + reg = <0x100000 0x500000>; + }; + partition@qspi-device-tree { + label = "qspi-device-tree"; + reg = <0x600000 0x20000>; + }; + partition@qspi-rootfs { + label = "qspi-rootfs"; + reg = <0x620000 0x5E0000>; + }; + partition@qspi-bitstream { + label = "qspi-bitstream"; + reg = <0xC00000 0x400000>; + }; + }; +}; + &sdhci0 { + u-boot,dm-pre-reloc; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_sdhci0_default>; diff --cc arch/arm/dts/zynq-zc770-xm011.dts index 8be3c958b8a,77e3bb0e631..1dd5357f4e0 --- a/arch/arm/dts/zynq-zc770-xm011.dts +++ b/arch/arm/dts/zynq-zc770-xm011.dts @@@ -48,54 -54,8 +48,55 @@@ }; }; +&nand0 { + status = "okay"; + arm,nand-cycle-t0 = <0x4>; + arm,nand-cycle-t1 = <0x4>; + arm,nand-cycle-t2 = <0x1>; + arm,nand-cycle-t3 = <0x2>; + arm,nand-cycle-t4 = <0x2>; + arm,nand-cycle-t5 = <0x2>; + arm,nand-cycle-t6 = <0x4>; + + partition@nand-fsbl-uboot { + label = "nand-fsbl-uboot"; + reg = <0x0 0x100000>; + }; + partition@nand-linux { + label = "nand-linux"; + reg = <0x100000 0x500000>; + }; + partition@nand-device-tree { + label = "nand-device-tree"; + reg = <0x600000 0x20000>; + }; + partition@nand-rootfs { + label = "nand-rootfs"; + reg = <0x620000 0x5E0000>; + }; + partition@nand-bitstream { + label = "nand-bitstream"; + reg = <0xC00000 0x400000>; + }; +}; + +&smcc { + status = "okay"; + arm,addr25 = <0x0>; + arm,nor-chip-sel0 = <0x0>; + arm,nor-chip-sel1 = <0x0>; + arm,sram-chip-sel0 = <0x0>; + arm,sram-chip-sel1 = <0x0>; +}; + +&spi0 { + status = "okay"; + num-cs = <4>; + is-decoded-cs = <0>; +}; + &uart1 { + u-boot,dm-pre-reloc; status = "okay"; }; diff --cc arch/arm/dts/zynq-zc770-xm012.dts index 5d1c4cd4765,3e1769acb51..3b3232d70b4 --- a/arch/arm/dts/zynq-zc770-xm012.dts +++ b/arch/arm/dts/zynq-zc770-xm012.dts @@@ -55,53 -61,7 +55,54 @@@ }; }; +&nor0 { + status = "okay"; + bank-width = <1>; + xlnx,sram-cycle-t0 = <0xb>; + xlnx,sram-cycle-t1 = <0xb>; + xlnx,sram-cycle-t2 = <0x4>; + xlnx,sram-cycle-t3 = <0x4>; + xlnx,sram-cycle-t4 = <0x3>; + xlnx,sram-cycle-t5 = <0x3>; + xlnx,sram-cycle-t6 = <0x2>; + partition@nor-fsbl-uboot { + label = "nor-fsbl-uboot"; + reg = <0x0 0x100000>; + }; + partition@nor-linux { + label = "nor-linux"; + reg = <0x100000 0x500000>; + }; + partition@nor-device-tree { + label = "nor-device-tree"; + reg = <0x600000 0x20000>; + }; + partition@nor-rootfs { + label = "nor-rootfs"; + reg = <0x620000 0x5E0000>; + }; + partition@nor-bitstream { + label = "nor-bitstream"; + reg = <0xC00000 0x400000>; + }; +}; + +&smcc { + status = "okay"; + arm,addr25 = <0x1>; + arm,nor-chip-sel0 = <0x1>; + arm,nor-chip-sel1 = <0x0>; + arm,sram-chip-sel0 = <0x0>; + arm,sram-chip-sel1 = <0x0>; +}; + +&spi1 { + status = "okay"; + num-cs = <4>; + is-decoded-cs = <0>; +}; + &uart1 { + u-boot,dm-pre-reloc; status = "okay"; }; diff --cc arch/arm/dts/zynq-zc770-xm013.dts index 77ba5bc9529,288e2483747..b8ed4134351 --- a/arch/arm/dts/zynq-zc770-xm013.dts +++ b/arch/arm/dts/zynq-zc770-xm013.dts @@@ -60,56 -74,7 +60,57 @@@ }; }; +&qspi { + status = "okay"; + is-dual = <1>; + num-cs = <1>; + flash@0 { + compatible = "n25q128a11"; + reg = <0x0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <50000000>; + #address-cells = <1>; + #size-cells = <1>; + partition@qspi-fsbl-uboot { + label = "qspi-fsbl-uboot"; + reg = <0x0 0x100000>; + }; + partition@qspi-linux { + label = "qspi-linux"; + reg = <0x100000 0x500000>; + }; + partition@qspi-device-tree { + label = "qspi-device-tree"; + reg = <0x600000 0x20000>; + }; + partition@qspi-rootfs { + label = "qspi-rootfs"; + reg = <0x620000 0x5E0000>; + }; + partition@qspi-bitstream { + label = "qspi-bitstream"; + reg = <0xC00000 0x400000>; + }; + }; +}; + +&spi0 { + status = "okay"; + num-cs = <4>; + is-decoded-cs = <0>; + eeprom: at25@0 { + at25,byte-len = <8192>; + at25,addr-mode = <2>; + at25,page-size = <32>; + + compatible = "atmel,at25"; + reg = <2>; + spi-max-frequency = <1000000>; + }; +}; + &uart0 { + u-boot,dm-pre-reloc; status = "okay"; }; diff --cc arch/arm/dts/zynq-zed.dts index dae6d141707,5ec59e2b4c6..5641b1d2f1a --- a/arch/arm/dts/zynq-zed.dts +++ b/arch/arm/dts/zynq-zed.dts @@@ -50,42 -50,8 +50,43 @@@ }; }; +&qspi { + status = "okay"; + is-dual = <0>; + num-cs = <1>; + flash@0 { + compatible = "n25q128a11"; + reg = <0x0>; + spi-tx-bus-width = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <50000000>; + #address-cells = <1>; + #size-cells = <1>; + partition@qspi-fsbl-uboot { + label = "qspi-fsbl-uboot"; + reg = <0x0 0x100000>; + }; + partition@qspi-linux { + label = "qspi-linux"; + reg = <0x100000 0x500000>; + }; + partition@qspi-device-tree { + label = "qspi-device-tree"; + reg = <0x600000 0x20000>; + }; + partition@qspi-rootfs { + label = "qspi-rootfs"; + reg = <0x620000 0x5E0000>; + }; + partition@qspi-bitstream { + label = "qspi-bitstream"; + reg = <0xC00000 0x400000>; + }; + }; +}; + &sdhci0 { + u-boot,dm-pre-reloc; status = "okay"; }; diff --cc arch/arm/include/asm/arch-zynqmp/hardware.h index 99d9d3021e8,bbf89d9dd74..a6eb8129aea --- a/arch/arm/include/asm/arch-zynqmp/hardware.h +++ b/arch/arm/include/asm/arch-zynqmp/hardware.h @@@ -24,11 -19,6 +21,8 @@@ #define ZYNQ_I2C_BASEADDR0 0xFF020000 #define ZYNQ_I2C_BASEADDR1 0xFF030000 - #define ZYNQ_SDHCI_BASEADDR0 0xFF160000 - #define ZYNQ_SDHCI_BASEADDR1 0xFF170000 - +#define ARASAN_NAND_BASEADDR 0xFF100000 + #define ZYNQMP_SATA_BASEADDR 0xFD0C0000 #define ZYNQMP_USB0_XHCI_BASEADDR 0xFE200000 diff --cc arch/arm/mach-zynq/Kconfig index dbd1c1f7532,d396a13b6f7..339e464beaf --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@@ -33,20 -33,7 +33,19 @@@ config TARGET_ZYNQ_ZC77 config TARGET_ZYNQ_ZYBO bool "Zynq Zybo Board" - select ZYNQ_CUSTOM_INIT +config TARGET_ZYNQ_AFX + bool "Zynq AFX Board" + select ZYNQ_CUSTOM_INIT + +config TARGET_ZYNQ_CSE + bool "Zynq CSE Board" + select ZYNQ_CUSTOM_INIT + +config TARGET_ZYNQ_CC108 + bool "Zynq CC108 Board" + select ZYNQ_CUSTOM_INIT + endchoice config SYS_BOARD diff --cc arch/arm/mach-zynq/u-boot-spl.lds index a78969129d4,ecdf6a031ec..4fb3b0b5cb0 --- a/arch/arm/mach-zynq/u-boot-spl.lds +++ b/arch/arm/mach-zynq/u-boot-spl.lds @@@ -30,23 -35,26 +30,31 @@@ SECTION . = ALIGN(4); .data : { *(.data*) - } > .sram + } . = ALIGN(4); + #ifdef CONFIG_SPL_DM + .u_boot_list : { + KEEP(*(SORT(.u_boot_list_*_driver_*))); + KEEP(*(SORT(.u_boot_list_*_uclass_*))); - } > .sram ++ } + + . = ALIGN(4); + #endif . = .; - __image_copy_end = .; + _image_binary_end = .; + .rel.dyn : { + __rel_dyn_start = .; + *(.rel*) + __rel_dyn_end = .; + } + _end = .; - /* Move BSS section to RAM because of FAT */ - .bss (NOLOAD) : { + .bss __rel_dyn_start (OVERLAY) : { __bss_start = .; *(.bss*) . = ALIGN(4); diff --cc board/xilinx/zynqmp/zynqmp.c index 6cf9563d720,2cf47125d43..453067e1842 --- a/board/xilinx/zynqmp/zynqmp.c +++ b/board/xilinx/zynqmp/zynqmp.c @@@ -9,9 -9,6 +9,7 @@@ #include #include #include - #include +#include #include #include #include diff --cc common/spl/spl_mmc.c index b956e3f574c,c1c29c02d7e..e938ba1d60d --- a/common/spl/spl_mmc.c +++ b/common/spl/spl_mmc.c @@@ -10,12 -10,11 +10,14 @@@ #include #include #include + #include #include + #include #include #include +#include +#include +#include DECLARE_GLOBAL_DATA_PTR; @@@ -104,68 -165,78 +168,107 @@@ static int mmc_load_image_raw_os(struc return mmc_load_image_raw_sector(mmc, CONFIG_SYS_MMCSD_RAW_MODE_KERNEL_SECTOR); } + #else + int spl_start_uboot(void) + { + return 1; + } + static int mmc_load_image_raw_os(struct mmc *mmc) + { + return -ENOSYS; + } #endif +#ifdef CONFIG_SPL_FPGA_SUPPORT +static int mmc_load_fpga_image_fat(struct mmc *mmc) +{ + int err; + int devnum = 0; + const fpga_desc *const desc = fpga_get_desc(devnum); + xilinx_desc *desc_xilinx = desc->devdesc; + + err = spl_load_image_fat(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + CONFIG_SPL_FPGA_LOAD_ARGS_NAME); + + if (err) { +#ifdef CONFIG_SPL_LIBCOMMON_SUPPORT + printf("spl: error reading image %s, err - %d\n", + CONFIG_SPL_FPGA_LOAD_ARGS_NAME, err); +#endif + return -1; + } +#ifdef CONFIG_SPL_FPGA_BIT + return fpga_loadbitstream(devnum, (char *)spl_image.load_addr, + desc_xilinx->size, BIT_FULL); +#else + return fpga_load(devnum, (const void *)spl_image.load_addr, + desc_xilinx->size, BIT_FULL); +#endif +} +#endif + - void spl_mmc_load_image(void) + #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION + int spl_mmc_do_fs_boot(struct mmc *mmc) { - struct mmc *mmc; - u32 boot_mode; - int err = 0; - __maybe_unused int part; - - #ifdef CONFIG_DM_MMC - struct udevice *dev; + int err = -ENOSYS; - mmc_initialize(NULL); - err = uclass_get_device(UCLASS_MMC, 0, &dev); - mmc = NULL; + #ifdef CONFIG_SPL_FAT_SUPPORT + if (!spl_start_uboot()) { + err = spl_load_image_fat_os(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); + if (!err) + return err; + } + #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + err = spl_load_image_fat(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); if (!err) - mmc = mmc_get_mmc_dev(dev); - #else - mmc_initialize(gd->bd); - - /* We register only one device. So, the dev id is always 0 */ - mmc = find_mmc_device(0); - if (!mmc) { - #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - puts("spl: mmc device not found\n"); + return err; #endif - hang(); + #endif + #ifdef CONFIG_SPL_EXT_SUPPORT + if (!spl_start_uboot()) { + err = spl_load_image_ext_os(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); + if (!err) + return err; } + #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME + err = spl_load_image_ext(&mmc->block_dev, + CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, + CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + if (!err) + return err; + #endif #endif - if (!err) - err = mmc_init(mmc); + #if defined(CONFIG_SPL_FAT_SUPPORT) || defined(CONFIG_SPL_EXT_SUPPORT) + err = -ENOENT; + #endif + return err; + } + #else + int spl_mmc_do_fs_boot(struct mmc *mmc) + { + return -ENOSYS; + } + #endif + + int spl_mmc_load_image(u32 boot_device) + { + struct mmc *mmc = NULL; + u32 boot_mode; + int err = 0; + __maybe_unused int part; + + err = spl_mmc_find_device(&mmc, boot_device); + if (err) + return err; + + err = mmc_init(mmc); if (err) { #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT printf("spl: mmc init failed with error: %d\n", err); @@@ -199,93 -289,17 +321,21 @@@ case MMCSD_MODE_FS: debug("spl: mmc boot mode: fs\n"); - #ifdef CONFIG_SYS_MMCSD_FS_BOOT_PARTITION - #ifdef CONFIG_SPL_FAT_SUPPORT - +#ifdef CONFIG_SPL_FPGA_SUPPORT + mmc_load_fpga_image_fat(mmc); +#endif + - #ifdef CONFIG_SPL_OS_BOOT - if (!spl_start_uboot()) { - err = spl_load_image_fat_os(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); - if (!err) - return; - } - #endif - #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME - err = spl_load_image_fat(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); + err = spl_mmc_do_fs_boot(mmc); if (!err) - return; - #endif - #endif - #ifdef CONFIG_SPL_EXT_SUPPORT - #ifdef CONFIG_SPL_OS_BOOT - if (!spl_start_uboot()) { - err = spl_load_image_ext_os(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION); - if (!err) - return; - } - #endif - #ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME - err = spl_load_image_ext(&mmc->block_dev, - CONFIG_SYS_MMCSD_FS_BOOT_PARTITION, - CONFIG_SPL_FS_LOAD_PAYLOAD_NAME); - if (!err) - return; - #endif - #endif - #endif - #ifdef CONFIG_SUPPORT_EMMC_BOOT - case MMCSD_MODE_EMMCBOOT: - /* - * We need to check what the partition is configured to. - * 1 and 2 match up to boot0 / boot1 and 7 is user data - * which is the first physical partition (0). - */ - part = (mmc->part_config >> 3) & PART_ACCESS_MASK; - - if (part == 7) - part = 0; - - if (mmc_switch_part(0, part)) { - #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - puts("spl: mmc partition switch failed\n"); - #endif - hang(); - } + return err; - #ifdef CONFIG_SPL_OS_BOOT - if (!spl_start_uboot()) { - err = mmc_load_image_raw_os(mmc); - if (!err) - return; - } - #endif - #if defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION) - err = mmc_load_image_raw_partition(mmc, - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION); - if (!err) - return; - #elif defined(CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR) - err = mmc_load_image_raw_sector(mmc, - CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR); - if (!err) - return; - #endif - #endif + break; case MMCSD_MODE_UNDEFINED: - default: #ifdef CONFIG_SPL_LIBCOMMON_SUPPORT - if (err) - puts("spl: mmc: no boot mode left to try\n"); - else - puts("spl: mmc: wrong boot mode\n"); + default: + puts("spl: mmc: wrong boot mode\n"); #endif - hang(); } + + return err; } diff --cc configs/xilinx_zynqmp_zcu102_defconfig index 3eae8b9dcac,00000000000..ea91951d33f mode 100644,000000..100644 --- a/configs/xilinx_zynqmp_zcu102_defconfig +++ b/configs/xilinx_zynqmp_zcu102_defconfig @@@ -1,21 -1,0 +1,23 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQMP=y +CONFIG_TARGET_ZYNQMP_ZCU102=y +CONFIG_ZYNQMP_QSPI=y +CONFIG_ZYNQMP_USB=y +CONFIG_SYS_TEXT_BASE=0x8000000 +CONFIG_DEFAULT_DEVICE_TREE="zynqmp-zcu102" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_SYS_PROMPT="ZynqMP> " +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_MEMTEST=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_PING=y +CONFIG_CMD_TIME=y +CONFIG_CMD_TIMER=y +CONFIG_OF_EMBED=y ++CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_BAR=y ++CONFIG_ZYNQ_GEM=y diff --cc configs/zynq_afx_qspi_RSA_defconfig index efa78da3986,00000000000..9ca1bd17847 mode 100644,000000..100644 --- a/configs/zynq_afx_qspi_RSA_defconfig +++ b/configs/zynq_afx_qspi_RSA_defconfig @@@ -1,14 -1,0 +1,13 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y +CONFIG_TARGET_ZYNQ_AFX=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-afx-qspi" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_EXTRA_OPTIONS="AFX_QSPI" +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +CONFIG_CMD_ZYNQ_RSA=y +CONFIG_OF_EMBED=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y diff --cc configs/zynq_afx_qspi_defconfig index 0542b06f591,00000000000..6622722489c mode 100644,000000..100644 --- a/configs/zynq_afx_qspi_defconfig +++ b/configs/zynq_afx_qspi_defconfig @@@ -1,10 -1,0 +1,9 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y +CONFIG_TARGET_ZYNQ_AFX=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-afx-qspi" +CONFIG_SYS_EXTRA_OPTIONS="AFX_QSPI" +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +CONFIG_OF_EMBED=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y diff --cc configs/zynq_cc108_defconfig index 74ba1fa7937,00000000000..74c446b9aa3 mode 100644,000000..100644 --- a/configs/zynq_cc108_defconfig +++ b/configs/zynq_cc108_defconfig @@@ -1,10 -1,0 +1,9 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y +CONFIG_TARGET_ZYNQ_CC108=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-cc108" +CONFIG_SPL=y +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +CONFIG_OF_EMBED=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y diff --cc configs/zynq_cse_qspi_defconfig index 106b029121b,00000000000..75a970ab096 mode 100644,000000..100644 --- a/configs/zynq_cse_qspi_defconfig +++ b/configs/zynq_cse_qspi_defconfig @@@ -1,36 -1,0 +1,35 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y +CONFIG_TARGET_ZYNQ_CSE=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-cse-qspi" +CONFIG_SYS_EXTRA_OPTIONS="CSE_QSPI" +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_GO is not set +# CONFIG_CMD_RUN is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_EXPORTENV is not set +# CONFIG_CMD_IMPORTENV is not set +# CONFIG_CMD_EDITENV is not set +# CONFIG_CMD_SAVEENV is not set +# CONFIG_CMD_ENV_EXISTS is not set +# CONFIG_CMD_CRC32 is not set +# CONFIG_CMD_DM is not set +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_FPGA is not set +# CONFIG_CMD_ECHO is not set +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SOURCE is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_NET is not set +# CONFIG_CMD_NFS is not set +# CONFIG_CMD_MISC is not set +CONFIG_OF_EMBED=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y diff --cc configs/zynq_microzed_defconfig index 176b8437520,e577c931735..a255d46d94f --- a/configs/zynq_microzed_defconfig +++ b/configs/zynq_microzed_defconfig @@@ -7,9 -6,14 +6,13 @@@ CONFIG_SPL= CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y + CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_SPI_FLASH_WINBOND=y + CONFIG_ZYNQ_GEM=y + CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_picozed_defconfig index 040da21b310,7d52d8e941b..7f9562bac24 --- a/configs/zynq_picozed_defconfig +++ b/configs/zynq_picozed_defconfig @@@ -3,9 -3,9 +3,11 @@@ CONFIG_ARCH_ZYNQ= CONFIG_TARGET_ZYNQ_PICOZED=y CONFIG_DEFAULT_DEVICE_TREE="zynq-picozed" CONFIG_SPL=y +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y + CONFIG_ZYNQ_GEM=y diff --cc configs/zynq_zc702_RSA_defconfig index ef00d2d4031,00000000000..b313dbbe98d mode 100644,000000..100644 --- a/configs/zynq_zc702_RSA_defconfig +++ b/configs/zynq_zc702_RSA_defconfig @@@ -1,16 -1,0 +1,15 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y - # CONFIG_SYS_MALLOC_F is not set +CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702" +CONFIG_SPL=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_ZYNQ_RSA=y +CONFIG_OF_EMBED=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y ++CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zc702_defconfig index bca951c7902,9d1b40d76ef..2383ab686b1 --- a/configs/zynq_zc702_defconfig +++ b/configs/zynq_zc702_defconfig @@@ -6,10 -5,18 +5,17 @@@ CONFIG_SPL= CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set + # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_SPI_FLASH_WINBOND=y + CONFIG_ZYNQ_GEM=y + CONFIG_DEBUG_UART=y + CONFIG_DEBUG_UART_ZYNQ=y + CONFIG_DEBUG_UART_BASE=0xe0001000 + CONFIG_DEBUG_UART_CLOCK=50000000 + CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zc706_RSA_defconfig index 475b6bb4c2f,00000000000..e2059ed92b2 mode 100644,000000..100644 --- a/configs/zynq_zc706_RSA_defconfig +++ b/configs/zynq_zc706_RSA_defconfig @@@ -1,18 -1,0 +1,17 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y - # CONFIG_SYS_MALLOC_F is not set +CONFIG_TARGET_ZYNQ_ZC706=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-zc706" +CONFIG_SPL=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_ZYNQ_RSA=y +CONFIG_OF_EMBED=y +CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y ++CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zc706_defconfig index d905719e180,bba91dfdfa7..0b8dd032090 --- a/configs/zynq_zc706_defconfig +++ b/configs/zynq_zc706_defconfig @@@ -7,11 -6,14 +6,13 @@@ CONFIG_SPL= CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_SPI_FLASH_WINBOND=y + CONFIG_ZYNQ_GEM=y + CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zc770_xm010_RSA_defconfig index e3735e44846,00000000000..86edcf9cb60 mode 100644,000000..100644 --- a/configs/zynq_zc770_xm010_RSA_defconfig +++ b/configs/zynq_zc770_xm010_RSA_defconfig @@@ -1,18 -1,0 +1,17 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y - # CONFIG_SYS_MALLOC_F is not set +CONFIG_TARGET_ZYNQ_ZC770=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010" +CONFIG_SPL=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010" +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_ZYNQ_RSA=y +CONFIG_OF_EMBED=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y ++CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zc770_xm010_defconfig index 857b4bfea98,96f0a794a38..9ee86c0943a --- a/configs/zynq_zc770_xm010_defconfig +++ b/configs/zynq_zc770_xm010_defconfig @@@ -8,12 -7,16 +7,14 @@@ CONFIG_FIT= CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010" +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_SPI_FLASH_SST=y -CONFIG_SPI_FLASH_WINBOND=y + CONFIG_ZYNQ_GEM=y CONFIG_ZYNQ_SPI=y + CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zc770_xm011_defconfig index 25e3f9d19a2,b0c535e88e1..ffdb2db209d --- a/configs/zynq_zc770_xm011_defconfig +++ b/configs/zynq_zc770_xm011_defconfig @@@ -8,9 -7,9 +7,11 @@@ CONFIG_FIT= CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM011" +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y + CONFIG_ZYNQ_GEM=y diff --cc configs/zynq_zc770_xm012_RSA_defconfig index 14dd44c4339,00000000000..f209b1707ab mode 100644,000000..100644 --- a/configs/zynq_zc770_xm012_RSA_defconfig +++ b/configs/zynq_zc770_xm012_RSA_defconfig @@@ -1,15 -1,0 +1,14 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y - # CONFIG_SYS_MALLOC_F is not set +CONFIG_TARGET_ZYNQ_ZC770=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012" +CONFIG_SPL=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012" +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_ZYNQ_RSA=y +CONFIG_OF_EMBED=y diff --cc configs/zynq_zc770_xm012_defconfig index ee095358d3e,7fb03eb0491..d8e6571083e --- a/configs/zynq_zc770_xm012_defconfig +++ b/configs/zynq_zc770_xm012_defconfig @@@ -8,8 -7,7 +7,10 @@@ CONFIG_FIT= CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012" +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y + CONFIG_ZYNQ_GEM=y diff --cc configs/zynq_zc770_xm013_RSA_defconfig index 33bee5a5fc3,00000000000..3ab24f8862e mode 100644,000000..100644 --- a/configs/zynq_zc770_xm013_RSA_defconfig +++ b/configs/zynq_zc770_xm013_RSA_defconfig @@@ -1,18 -1,0 +1,16 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y - # CONFIG_SYS_MALLOC_F is not set +CONFIG_TARGET_ZYNQ_ZC770=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013" +CONFIG_SPL=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013" +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_ZYNQ_RSA=y +CONFIG_OF_EMBED=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y diff --cc configs/zynq_zc770_xm013_defconfig index 14b28192c11,67665127b5b..8cf58420e8a --- a/configs/zynq_zc770_xm013_defconfig +++ b/configs/zynq_zc770_xm013_defconfig @@@ -8,11 -7,9 +7,12 @@@ CONFIG_FIT= CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013" +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y + CONFIG_ZYNQ_GEM=y diff --cc configs/zynq_zed_RSA_defconfig index 4fb42f40cea,00000000000..f2b8e26b9db mode 100644,000000..100644 --- a/configs/zynq_zed_RSA_defconfig +++ b/configs/zynq_zed_RSA_defconfig @@@ -1,17 -1,0 +1,16 @@@ +CONFIG_ARM=y +CONFIG_ARCH_ZYNQ=y - # CONFIG_SYS_MALLOC_F is not set +CONFIG_TARGET_ZYNQ_ZED=y +CONFIG_DEFAULT_DEVICE_TREE="zynq-zed" +CONFIG_SPL=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " +# CONFIG_CMD_IMLS is not set +# CONFIG_CMD_FLASH is not set +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_ZYNQ_RSA=y +CONFIG_OF_EMBED=y +CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y ++CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zed_defconfig index 717aa193725,058bb05ba65..3f6b2cc0ab6 --- a/configs/zynq_zed_defconfig +++ b/configs/zynq_zed_defconfig @@@ -7,11 -6,14 +6,13 @@@ CONFIG_SPL= CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y CONFIG_SPI_FLASH=y - CONFIG_SPI_FLASH_BAR=y -CONFIG_SPI_FLASH_SPANSION=y -CONFIG_SPI_FLASH_STMICRO=y -CONFIG_SPI_FLASH_WINBOND=y + CONFIG_ZYNQ_GEM=y + CONFIG_ZYNQ_QSPI=y diff --cc configs/zynq_zybo_defconfig index 5cf49b6f828,231483e3dbd..cd48fbb4199 --- a/configs/zynq_zybo_defconfig +++ b/configs/zynq_zybo_defconfig @@@ -7,9 -6,16 +6,17 @@@ CONFIG_SPL= CONFIG_FIT=y CONFIG_FIT_VERBOSE=y CONFIG_FIT_SIGNATURE=y +CONFIG_SYS_PROMPT="Zynq> " # CONFIG_CMD_IMLS is not set # CONFIG_CMD_FLASH is not set + CONFIG_CMD_GPIO=y # CONFIG_CMD_SETEXPR is not set +CONFIG_OF_EMBED=y CONFIG_NET_RANDOM_ETHADDR=y ++CONFIG_SPI_FLASH=y + CONFIG_ZYNQ_GEM=y + CONFIG_DEBUG_UART=y + CONFIG_DEBUG_UART_ZYNQ=y + CONFIG_DEBUG_UART_BASE=0xe0001000 + CONFIG_DEBUG_UART_CLOCK=50000000 -CONFIG_SPI_FLASH=y -CONFIG_SPI_FLASH_SPANSION=y + CONFIG_ZYNQ_QSPI=y diff --cc drivers/mmc/zynq_sdhci.c index 7720d239591,4fe3da93b20..f21ea524af9 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@@ -11,30 -12,20 +12,25 @@@ #include #include #include - #include +#ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ +# define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0 +#endif + - int zynq_sdhci_init(phys_addr_t regbase) + static int arasan_sdhci_probe(struct udevice *dev) { - struct sdhci_host *host = NULL; + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct sdhci_host *host = dev_get_priv(dev); - host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); - if (!host) { - printf("zynq_sdhci_init: sdhci_host malloc fail\n"); - return 1; - } - - host->name = "zynq_sdhci"; - host->ioaddr = (void *)regbase; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B; host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, 0); + add_sdhci(host, CONFIG_ZYNQ_SDHCI_MAX_FREQ, + CONFIG_ZYNQ_SDHCI_MIN_FREQ); + + upriv->mmc = host->mmc; + return 0; } diff --cc drivers/mtd/spi/sf_internal.h index aba73c187aa,ed5c391dc2c..782cfe0a152 --- a/drivers/mtd/spi/sf_internal.h +++ b/drivers/mtd/spi/sf_internal.h @@@ -44,14 -44,15 +44,19 @@@ enum #endif SECT_32K = 1 << 1, E_FSR = 1 << 2, - SST_BP = 1 << 3, - SST_WP = 1 << 4, - WR_QPP = 1 << 5, - SST_WR = 1 << 3, ++ SST_WP = 1 << 3, + WR_QPP = 1 << 4, ++ SST_BP = 1 << 5, + SST_LOCKBP = 1 << 6, }; +#define SST_WR (SST_BP | SST_WP) + + enum spi_nor_option_flags { + SNOR_F_SST_WR = (1 << 0), + SNOR_F_USE_FSR = (1 << 1), + }; + #define SPI_FLASH_3B_ADDR_LEN 3 #define SPI_FLASH_CMD_LEN (1 + SPI_FLASH_3B_ADDR_LEN) #define SPI_FLASH_16MB_BOUN 0x1000000 @@@ -60,10 -61,9 +65,12 @@@ #define SPI_FLASH_CFI_MFR_SPANSION 0x01 #define SPI_FLASH_CFI_MFR_STMICRO 0x20 #define SPI_FLASH_CFI_MFR_MACRONIX 0xc2 + #define SPI_FLASH_CFI_MFR_SST 0xbf #define SPI_FLASH_CFI_MFR_WINBOND 0xef + #define SPI_FLASH_CFI_MFR_ATMEL 0x1f +#define SPI_FLASH_CFI_MFR_ISSI 0x9d + +#define SPI_FLASH_SPANSION_S25FS_FMLY 0x81 /* Erase commands */ #define CMD_ERASE_4K 0x20 @@@ -194,14 -190,6 +201,8 @@@ static inline int spi_flash_cmd_write_d return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0); } +int spi_flash_cmd_bp_unlock(struct spi_flash *flash); + - /* - * Send the read status command to the device and wait for the wip - * (write-in-progress) bit to clear itself. - */ - int spi_flash_cmd_wait_ready(struct spi_flash *flash, unsigned long timeout); - /* * Used for spi_flash write operation * - SPI claim diff --cc drivers/mtd/spi/sf_probe.c index 90ab4191135,0cafc291230..0e215d3e9c8 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@@ -473,57 -40,9 +40,44 @@@ static int spi_flash_probe_slave(struc debug("SF: Failed to claim SPI bus: %d\n", ret); return ret; } - ++#if 0 + if (spi->option == SF_DUAL_PARALLEL_FLASH) + spi->flags |= SPI_XFER_LOWER; + /* Read the ID codes */ + ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); + if (ret) { + printf("SF: Failed to get idcodes\n"); + goto err_read_id; + } + +#ifdef CONFIG_SPI_GENERIC + if (spi->option == SF_DUAL_PARALLEL_FLASH) { + spi->flags |= SPI_XFER_UPPER; + ret = spi_flash_cmd(spi, CMD_READ_ID, idcode_up, + sizeof(idcode_up)); + if (ret) { + printf("SF: Failed to get idcodes\n"); + goto err_read_id; + } + for (i = 0; i < sizeof(idcode); i++) { + if (idcode[i] != idcode_up[i]) { + printf("SF: Failed to get same idcodes\n"); + goto err_read_id; + } + } + } +#endif +#ifdef DEBUG + printf("SF: Got idcodes\n"); + print_buffer(0, idcode, 1, sizeof(idcode), 0); +#endif + + if (spi_flash_validate_params(spi, idcode, flash)) { - ret = -EINVAL; - goto err_read_id; - } + - /* Set the quad enable bit - only for quad commands */ - if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || - (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || - (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { - if (spi_flash_set_qeb(flash, idcode[0])) { - debug("SF: Fail to set QEB for %02x\n", idcode[0]); - ret = -EINVAL; - goto err_read_id; - } - } ++#endif - #if CONFIG_IS_ENABLED(OF_CONTROL) - if (spi_flash_decode_fdt(gd->fdt_blob, flash)) { - debug("SF: FDT decode error\n"); + ret = spi_flash_scan(flash); + if (ret) { ret = -EINVAL; goto err_read_id; } diff --cc drivers/mtd/spi/spi_flash.c index 00000000000,b7b7f0044e7..ed259b2c026 mode 000000,100644..100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@@ -1,0 -1,1115 +1,1435 @@@ + /* + * SPI Flash Core + * + * Copyright (C) 2015 Jagan Teki + * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc. + * Copyright (C) 2010 Reinhard Meyer, EMK Elektronik + * Copyright (C) 2008 Atmel Corporation + * + * SPDX-License-Identifier: GPL-2.0+ + */ + + #include + #include + #include + #include + #include + #include + #include + + #include "sf_internal.h" + + DECLARE_GLOBAL_DATA_PTR; + -static void spi_flash_addr(u32 addr, u8 *cmd) ++static void spi_flash_addr(u32 addr, u8 *cmd, u8 four_byte) + { + /* cmd[0] is actual command */ - cmd[1] = addr >> 16; - cmd[2] = addr >> 8; - cmd[3] = addr >> 0; ++ if (four_byte) { ++ cmd[1] = addr >> 24; ++ cmd[2] = addr >> 16; ++ cmd[3] = addr >> 8; ++ cmd[4] = addr >> 0; ++ } else { ++ cmd[1] = addr >> 16; ++ cmd[2] = addr >> 8; ++ cmd[3] = addr >> 0; ++ } + } + + /* Read commands array */ + static u8 spi_read_cmds_array[] = { + CMD_READ_ARRAY_SLOW, + CMD_READ_ARRAY_FAST, + CMD_READ_DUAL_OUTPUT_FAST, + CMD_READ_DUAL_IO_FAST, + CMD_READ_QUAD_OUTPUT_FAST, + CMD_READ_QUAD_IO_FAST, + }; + + static int read_sr(struct spi_flash *flash, u8 *rs) + { + int ret; + u8 cmd; + + cmd = CMD_READ_STATUS; + ret = spi_flash_read_common(flash, &cmd, 1, rs, 1); + if (ret < 0) { + debug("SF: fail to read status register\n"); + return ret; + } + + return 0; + } + + static int read_fsr(struct spi_flash *flash, u8 *fsr) + { + int ret; + const u8 cmd = CMD_FLAG_STATUS; + + ret = spi_flash_read_common(flash, &cmd, 1, fsr, 1); + if (ret < 0) { + debug("SF: fail to read flag status register\n"); + return ret; + } + + return 0; + } + + static int write_sr(struct spi_flash *flash, u8 ws) + { + u8 cmd; + int ret; + + cmd = CMD_WRITE_STATUS; + ret = spi_flash_write_common(flash, &cmd, 1, &ws, 1); + if (ret < 0) { + debug("SF: fail to write status register\n"); + return ret; + } + + return 0; + } + + #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + static int read_cr(struct spi_flash *flash, u8 *rc) + { + int ret; + u8 cmd; + + cmd = CMD_READ_CONFIG; + ret = spi_flash_read_common(flash, &cmd, 1, rc, 1); + if (ret < 0) { + debug("SF: fail to read config register\n"); + return ret; + } + + return 0; + } + + static int write_cr(struct spi_flash *flash, u8 wc) + { + u8 data[2]; ++#ifdef CONFIG_SPI_GENERIC ++ u8 dataup[2]; ++#endif + u8 cmd; + int ret; + ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_LOWER; ++#endif + ret = read_sr(flash, &data[0]); + if (ret < 0) + return ret; + ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) { ++ flash->spi->flags |= SPI_XFER_UPPER; ++ ret = read_sr(flash, &dataup[0]); ++ if (ret < 0) ++ return ret; ++ } ++#endif ++ ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_LOWER; ++#endif ++ + cmd = CMD_WRITE_STATUS; + data[1] = wc; + ret = spi_flash_write_common(flash, &cmd, 1, &data, 2); + if (ret) { + debug("SF: fail to write config register\n"); + return ret; + } + ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) { ++ flash->spi->flags |= SPI_XFER_UPPER; ++ dataup[1] = wc; ++ ret = spi_flash_write_common(flash, &cmd, 1, &dataup, 2); ++ if (ret) { ++ debug("SF: fail to write config register\n"); ++ return ret; ++ } ++ } ++#endif ++ + return 0; + } + #endif + + #ifdef CONFIG_SPI_FLASH_BAR + static int spi_flash_write_bar(struct spi_flash *flash, u32 offset) + { - u8 cmd, bank_sel; ++ u8 cmd, bank_sel, upage_curr; + int ret; + + bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift); - if (bank_sel == flash->bank_curr) - goto bar_end; ++ ++ upage_curr = flash->spi->flags & SPI_XFER_U_PAGE; ++ ++ if (flash->dual_flash != SF_DUAL_STACKED_FLASH) { ++ if (flash->bank_curr == bank_sel) { ++ debug("SF: not require to enable bank%d\n", bank_sel); ++ goto bar_end; ++ } ++ } else if (flash->upage_prev == upage_curr) { ++ if (flash->bank_curr == bank_sel) { ++ debug("SF: not require to enable bank%d\n", bank_sel); ++ goto bar_end; ++ } ++ } else { ++ flash->upage_prev = upage_curr; ++ } + + cmd = flash->bank_write_cmd; + ret = spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); + if (ret < 0) { + debug("SF: fail to write bank register\n"); + return ret; + } + + bar_end: + flash->bank_curr = bank_sel; + return flash->bank_curr; + } + + static int spi_flash_read_bar(struct spi_flash *flash, u8 idcode0) + { + u8 curr_bank = 0; + int ret; + + if (flash->size <= SPI_FLASH_16MB_BOUN) + goto bank_end; + + switch (idcode0) { + case SPI_FLASH_CFI_MFR_SPANSION: + flash->bank_read_cmd = CMD_BANKADDR_BRRD; + flash->bank_write_cmd = CMD_BANKADDR_BRWR; + break; + default: + flash->bank_read_cmd = CMD_EXTNADDR_RDEAR; + flash->bank_write_cmd = CMD_EXTNADDR_WREAR; + } + + ret = spi_flash_read_common(flash, &flash->bank_read_cmd, 1, + &curr_bank, 1); + if (ret) { + debug("SF: fail to read bank addr register\n"); + return ret; + } + + bank_end: + flash->bank_curr = curr_bank; + return 0; + } + #endif + + #ifdef CONFIG_SF_DUAL_FLASH + static void spi_flash_dual(struct spi_flash *flash, u32 *addr) + { + switch (flash->dual_flash) { + case SF_DUAL_STACKED_FLASH: + if (*addr >= (flash->size >> 1)) { + *addr -= flash->size >> 1; + flash->spi->flags |= SPI_XFER_U_PAGE; + } else { + flash->spi->flags &= ~SPI_XFER_U_PAGE; + } + break; + case SF_DUAL_PARALLEL_FLASH: + *addr >>= flash->shift; + break; + default: + debug("SF: Unsupported dual_flash=%d\n", flash->dual_flash); + break; + } + } + #endif + + static int spi_flash_sr_ready(struct spi_flash *flash) + { + u8 sr; + int ret; ++#ifdef CONFIG_SPI_GENERIC ++ u8 sr_up; ++#endif + - ret = read_sr(flash, &sr); - if (ret < 0) - return ret; ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) { ++ flash->spi->flags |= SPI_XFER_LOWER; ++ ret = read_sr(flash, &sr); ++ if (ret < 0) ++ return ret; + - return !(sr & STATUS_WIP); ++ flash->spi->flags |= SPI_XFER_UPPER; ++ ret = read_sr(flash, &sr_up); ++ if (ret < 0) ++ return ret; ++ ++ sr = (!(sr & STATUS_WIP) && !(sr_up & STATUS_WIP)); ++ return sr; ++ } else { ++#endif ++ ret = read_sr(flash, &sr); ++ if (ret < 0) ++ return ret; ++ return !(sr & STATUS_WIP); ++#ifdef CONFIG_SPI_GENERIC ++ } ++#endif + } + + static int spi_flash_fsr_ready(struct spi_flash *flash) + { + u8 fsr; + int ret; ++#ifdef CONFIG_SPI_GENERIC ++ u8 fsr_up; ++#endif ++ ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) { ++ flash->spi->flags |= SPI_XFER_LOWER; ++ ret = read_fsr(flash, &fsr); ++ if (ret < 0) ++ return ret; + ++ flash->spi->flags |= SPI_XFER_UPPER; ++ ret = read_fsr(flash, &fsr_up); ++ if (ret < 0) ++ return ret; ++ ++ fsr = ((fsr & STATUS_PEC) && (fsr_up & STATUS_PEC)); ++ return fsr; ++ } else { ++#endif + ret = read_fsr(flash, &fsr); + if (ret < 0) + return ret; - + return fsr & STATUS_PEC; ++#ifdef CONFIG_SPI_GENERIC ++ } ++#endif + } + + static int spi_flash_ready(struct spi_flash *flash) + { + int sr, fsr; + + sr = spi_flash_sr_ready(flash); + if (sr < 0) + return sr; + + fsr = 1; + if (flash->flags & SNOR_F_USE_FSR) { + fsr = spi_flash_fsr_ready(flash); + if (fsr < 0) + return fsr; + } + + return sr && fsr; + } + + static int spi_flash_cmd_wait_ready(struct spi_flash *flash, + unsigned long timeout) + { + int timebase, ret; + + timebase = get_timer(0); + + while (get_timer(timebase) < timeout) { + ret = spi_flash_ready(flash); + if (ret < 0) + return ret; + if (ret) + return 0; + } + + printf("SF: Timeout!\n"); + + return -ETIMEDOUT; + } + + int spi_flash_write_common(struct spi_flash *flash, const u8 *cmd, + size_t cmd_len, const void *buf, size_t buf_len) + { + struct spi_slave *spi = flash->spi; + unsigned long timeout = SPI_FLASH_PROG_TIMEOUT; + int ret; + + if (buf == NULL) + timeout = SPI_FLASH_PAGE_ERASE_TIMEOUT; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + + ret = spi_flash_cmd_write_enable(flash); + if (ret < 0) { + debug("SF: enabling write failed\n"); + return ret; + } + + ret = spi_flash_cmd_write(spi, cmd, cmd_len, buf, buf_len); + if (ret < 0) { + debug("SF: write cmd failed\n"); + return ret; + } + + ret = spi_flash_cmd_wait_ready(flash, timeout); + if (ret < 0) { + debug("SF: write %s timed out\n", + timeout == SPI_FLASH_PROG_TIMEOUT ? + "program" : "page erase"); + return ret; + } + + spi_release_bus(spi); + + return ret; + } + + int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) + { - u32 erase_size, erase_addr; - u8 cmd[SPI_FLASH_CMD_LEN]; ++ u32 erase_size, erase_addr, bank_addr; ++ u8 cmd[SPI_FLASH_CMD_LEN + 1]; + int ret = -1; ++ u32 cmdlen; + + erase_size = flash->erase_size; + if (offset % erase_size || len % erase_size) { + debug("SF: Erase offset/length not multiple of erase size\n"); + return -1; + } + + if (flash->flash_is_locked) { + if (flash->flash_is_locked(flash, offset, len) > 0) { + printf("offset 0x%x is protected and cannot be erased\n", + offset); + return -EINVAL; + } + } + + cmd[0] = flash->erase_cmd; + while (len) { + erase_addr = offset; ++ bank_addr = offset; + + #ifdef CONFIG_SF_DUAL_FLASH + if (flash->dual_flash > SF_SINGLE_FLASH) + spi_flash_dual(flash, &erase_addr); ++ if (flash->dual_flash == SF_DUAL_STACKED_FLASH) ++ bank_addr = erase_addr; + #endif ++ ++ if (flash->spi->bytemode != SPI_4BYTE_MODE) { + #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bar(flash, erase_addr); - if (ret < 0) - return ret; ++ ret = spi_flash_write_bar(flash, bank_addr); ++ if (ret < 0) ++ return ret; + #endif - spi_flash_addr(erase_addr, cmd); ++ spi_flash_addr(erase_addr, cmd, 0); ++ cmdlen = SPI_FLASH_CMD_LEN; ++ } else { ++ spi_flash_addr(erase_addr, cmd, 1); ++ cmdlen = SPI_FLASH_CMD_LEN + 1; ++ } + + debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], + cmd[2], cmd[3], erase_addr); + - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_STRIPE; ++#endif ++ ret = spi_flash_write_common(flash, cmd, cmdlen, NULL, 0); + if (ret < 0) { + debug("SF: erase failed\n"); + break; + } + + offset += erase_size; + len -= erase_size; + } + + return ret; + } + + int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, + size_t len, const void *buf) + { + unsigned long byte_addr, page_size; - u32 write_addr; ++ u32 write_addr, bank_addr; + size_t chunk_len, actual; - u8 cmd[SPI_FLASH_CMD_LEN]; ++ u8 cmd[SPI_FLASH_CMD_LEN + 1]; ++ u32 cmdlen; + int ret = -1; + + page_size = flash->page_size; + + if (flash->flash_is_locked) { + if (flash->flash_is_locked(flash, offset, len) > 0) { + printf("offset 0x%x is protected and cannot be written\n", + offset); + return -EINVAL; + } + } + + cmd[0] = flash->write_cmd; + for (actual = 0; actual < len; actual += chunk_len) { + write_addr = offset; ++ bank_addr = offset; + + #ifdef CONFIG_SF_DUAL_FLASH + if (flash->dual_flash > SF_SINGLE_FLASH) + spi_flash_dual(flash, &write_addr); ++ if (flash->dual_flash == SF_DUAL_STACKED_FLASH) ++ bank_addr = write_addr; + #endif ++ ++ if (flash->spi->bytemode != SPI_4BYTE_MODE) { + #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bar(flash, write_addr); - if (ret < 0) - return ret; ++ ret = spi_flash_write_bar(flash, bank_addr); ++ if (ret < 0) ++ return ret; + #endif ++ } ++ + byte_addr = offset % page_size; + chunk_len = min(len - actual, (size_t)(page_size - byte_addr)); + + if (flash->spi->max_write_size) + chunk_len = min(chunk_len, + (size_t)flash->spi->max_write_size); + - spi_flash_addr(write_addr, cmd); ++ if (flash->spi->bytemode == SPI_4BYTE_MODE) { ++ spi_flash_addr(write_addr, cmd, 1); ++ cmdlen = SPI_FLASH_CMD_LEN + 1; ++ } else { ++ spi_flash_addr(write_addr, cmd, 0); ++ cmdlen = SPI_FLASH_CMD_LEN; ++ } + + debug("SF: 0x%p => cmd = { 0x%02x 0x%02x%02x%02x } chunk_len = %zu\n", + buf + actual, cmd[0], cmd[1], cmd[2], cmd[3], chunk_len); + - ret = spi_flash_write_common(flash, cmd, sizeof(cmd), ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_STRIPE; ++#endif ++ ret = spi_flash_write_common(flash, cmd, cmdlen, + buf + actual, chunk_len); + if (ret < 0) { + debug("SF: write failed\n"); + break; + } + + offset += chunk_len; + } + + return ret; + } + + int spi_flash_read_common(struct spi_flash *flash, const u8 *cmd, + size_t cmd_len, void *data, size_t data_len) + { + struct spi_slave *spi = flash->spi; + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + + ret = spi_flash_cmd_read(spi, cmd, cmd_len, data, data_len); + if (ret < 0) { + debug("SF: read cmd failed\n"); + return ret; + } + + spi_release_bus(spi); + + return ret; + } + + void __weak spi_flash_copy_mmap(void *data, void *offset, size_t len) + { + memcpy(data, offset, len); + } + + int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, + size_t len, void *data) + { + u8 *cmd, cmdsz; - u32 remain_len, read_len, read_addr; ++ u32 remain_len, read_len, read_addr, bank_addr; + int bank_sel = 0; + int ret = -1; + + /* Handle memory-mapped SPI */ + if (flash->memory_map) { + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: unable to claim SPI bus\n"); + return ret; + } + spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP); + spi_flash_copy_mmap(data, flash->memory_map + offset, len); + spi_xfer(flash->spi, 0, NULL, NULL, SPI_XFER_MMAP_END); + spi_release_bus(flash->spi); + return 0; + } + + cmdsz = SPI_FLASH_CMD_LEN + flash->dummy_byte; ++ ++ if (flash->spi->bytemode == SPI_4BYTE_MODE) ++ cmdsz += 1; ++ + cmd = calloc(1, cmdsz); + if (!cmd) { + debug("SF: Failed to allocate cmd\n"); + return -ENOMEM; + } + + cmd[0] = flash->read_cmd; + while (len) { + read_addr = offset; ++ bank_addr = offset; + + #ifdef CONFIG_SF_DUAL_FLASH + if (flash->dual_flash > SF_SINGLE_FLASH) + spi_flash_dual(flash, &read_addr); ++ if (flash->dual_flash == SF_DUAL_STACKED_FLASH) ++ bank_addr = read_addr; + #endif ++ ++ if (flash->spi->bytemode != SPI_4BYTE_MODE) { + #ifdef CONFIG_SPI_FLASH_BAR - ret = spi_flash_write_bar(flash, read_addr); - if (ret < 0) - return ret; - bank_sel = flash->bank_curr; ++ bank_sel = spi_flash_write_bar(flash, bank_addr); ++ if (bank_sel < 0) ++ return ret; ++ if ((flash->dual_flash == SF_DUAL_STACKED_FLASH) && ++ (flash->spi->flags & SPI_XFER_U_PAGE)) ++ bank_sel += (flash->size >> 1)/ ++ SPI_FLASH_16MB_BOUN; + #endif - remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * - (bank_sel + 1)) - offset; - if (len < remain_len) ++ remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) * ++ (bank_sel + 1)) - offset; ++ if (len < remain_len) ++ read_len = len; ++ else ++ read_len = remain_len; ++ } else { + read_len = len; - else - read_len = remain_len; ++ } + - spi_flash_addr(read_addr, cmd); ++ if (flash->spi->bytemode == SPI_4BYTE_MODE) ++ spi_flash_addr(read_addr, cmd, 1); ++ else ++ spi_flash_addr(read_addr, cmd, 0); + ++ debug("%s: Byte Mode:0x%x\n", __func__, flash->spi->bytemode); ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash == SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_STRIPE; ++#endif + ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); + if (ret < 0) { + debug("SF: read failed\n"); + break; + } + + offset += read_len; + len -= read_len; + data += read_len; + } + + free(cmd); + return ret; + } + + #ifdef CONFIG_SPI_FLASH_SST + static int sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf) + { + int ret; + u8 cmd[4] = { + CMD_SST_BP, + offset >> 16, + offset >> 8, + offset, + }; + + debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", + spi_w8r8(flash->spi, CMD_READ_STATUS), buf, cmd[0], offset); + + ret = spi_flash_cmd_write_enable(flash); + if (ret) + return ret; + + ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1); + if (ret) + return ret; + + return spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + } + + int sst_write_wp(struct spi_flash *flash, u32 offset, size_t len, + const void *buf) + { + size_t actual, cmd_len; + int ret; + u8 cmd[4]; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + /* If the data is not word aligned, write out leading single byte */ + actual = offset % 2; + if (actual) { + ret = sst_byte_write(flash, offset, buf); + if (ret) + goto done; + } + offset += actual; + + ret = spi_flash_cmd_write_enable(flash); + if (ret) + goto done; + + cmd_len = 4; + cmd[0] = CMD_SST_AAI_WP; + cmd[1] = offset >> 16; + cmd[2] = offset >> 8; + cmd[3] = offset; + + for (; actual < len - 1; actual += 2) { + debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n", + spi_w8r8(flash->spi, CMD_READ_STATUS), buf + actual, + cmd[0], offset); + + ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len, + buf + actual, 2); + if (ret) { + debug("SF: sst word program failed\n"); + break; + } + + ret = spi_flash_cmd_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT); + if (ret) + break; + + cmd_len = 1; + offset += 2; + } + + if (!ret) + ret = spi_flash_cmd_write_disable(flash); + + /* If there is a single trailing byte, write it out */ + if (!ret && actual != len) + ret = sst_byte_write(flash, offset, buf + actual); + + done: + debug("SF: sst: program %s %zu bytes @ 0x%zx\n", + ret ? "failure" : "success", len, offset - actual); + + spi_release_bus(flash->spi); + return ret; + } + + int sst_write_bp(struct spi_flash *flash, u32 offset, size_t len, + const void *buf) + { + size_t actual; + int ret; + + ret = spi_claim_bus(flash->spi); + if (ret) { + debug("SF: Unable to claim SPI bus\n"); + return ret; + } + + for (actual = 0; actual < len; actual++) { + ret = sst_byte_write(flash, offset, buf + actual); + if (ret) { + debug("SF: sst byte program failed\n"); + break; + } + offset++; + } + + if (!ret) + ret = spi_flash_cmd_write_disable(flash); + + debug("SF: sst: program %s %zu bytes @ 0x%zx\n", + ret ? "failure" : "success", len, offset - actual); + + spi_release_bus(flash->spi); + return ret; + } + #endif + + #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) + static void stm_get_locked_range(struct spi_flash *flash, u8 sr, loff_t *ofs, + u32 *len) + { + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + int shift = ffs(mask) - 1; + int pow; + + if (!(sr & mask)) { + /* No protection */ + *ofs = 0; + *len = 0; + } else { + pow = ((sr & mask) ^ mask) >> shift; + *len = flash->size >> pow; + *ofs = flash->size - *len; + } + } + + /* + * Return 1 if the entire region is locked, 0 otherwise + */ + static int stm_is_locked_sr(struct spi_flash *flash, u32 ofs, u32 len, + u8 sr) + { + loff_t lock_offs; + u32 lock_len; + + stm_get_locked_range(flash, sr, &lock_offs, &lock_len); + + return (ofs + len <= lock_offs + lock_len) && (ofs >= lock_offs); + } + + /* + * Check if a region of the flash is (completely) locked. See stm_lock() for + * more info. + * + * Returns 1 if entire region is locked, 0 if any portion is unlocked, and + * negative on errors. + */ + int stm_is_locked(struct spi_flash *flash, u32 ofs, size_t len) + { + int status; + u8 sr; + + status = read_sr(flash, &sr); + if (status < 0) + return status; + + return stm_is_locked_sr(flash, ofs, len, sr); + } + + /* + * Lock a region of the flash. Compatible with ST Micro and similar flash. + * Supports only the block protection bits BP{0,1,2} in the status register + * (SR). Does not support these features found in newer SR bitfields: + * - TB: top/bottom protect - only handle TB=0 (top protect) + * - SEC: sector/block protect - only handle SEC=0 (block protect) + * - CMP: complement protect - only support CMP=0 (range is not complemented) + * + * Sample table portion for 8MB flash (Winbond w25q64fw): + * + * SEC | TB | BP2 | BP1 | BP0 | Prot Length | Protected Portion + * -------------------------------------------------------------------------- + * X | X | 0 | 0 | 0 | NONE | NONE + * 0 | 0 | 0 | 0 | 1 | 128 KB | Upper 1/64 + * 0 | 0 | 0 | 1 | 0 | 256 KB | Upper 1/32 + * 0 | 0 | 0 | 1 | 1 | 512 KB | Upper 1/16 + * 0 | 0 | 1 | 0 | 0 | 1 MB | Upper 1/8 + * 0 | 0 | 1 | 0 | 1 | 2 MB | Upper 1/4 + * 0 | 0 | 1 | 1 | 0 | 4 MB | Upper 1/2 + * X | X | 1 | 1 | 1 | 8 MB | ALL + * + * Returns negative on errors, 0 on success. + */ + int stm_lock(struct spi_flash *flash, u32 ofs, size_t len) + { + u8 status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + int ret; + + ret = read_sr(flash, &status_old); + if (ret < 0) + return ret; + + /* SPI NOR always locks to the end */ + if (ofs + len != flash->size) { + /* Does combined region extend to end? */ + if (!stm_is_locked_sr(flash, ofs + len, flash->size - ofs - len, + status_old)) + return -EINVAL; + len = flash->size - ofs; + } + + /* + * Need smallest pow such that: + * + * 1 / (2^pow) <= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = ceil(log2(size / len)) = log2(size) - floor(log2(len)) + */ + pow = ilog2(flash->size) - ilog2(len); + val = mask - (pow << shift); + if (val & ~mask) + return -EINVAL; + + /* Don't "lock" with no region! */ + if (!(val & mask)) + return -EINVAL; + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not unlock other areas */ + if ((status_new & mask) <= (status_old & mask)) + return -EINVAL; + + write_sr(flash, status_new); + + return 0; + } + + /* + * Unlock a region of the flash. See stm_lock() for more info + * + * Returns negative on errors, 0 on success. + */ + int stm_unlock(struct spi_flash *flash, u32 ofs, size_t len) + { + uint8_t status_old, status_new; + u8 mask = SR_BP2 | SR_BP1 | SR_BP0; + u8 shift = ffs(mask) - 1, pow, val; + int ret; + + ret = read_sr(flash, &status_old); + if (ret < 0) + return ret; + + /* Cannot unlock; would unlock larger region than requested */ + if (stm_is_locked_sr(flash, ofs - flash->erase_size, flash->erase_size, + status_old)) + return -EINVAL; + /* + * Need largest pow such that: + * + * 1 / (2^pow) >= (len / size) + * + * so (assuming power-of-2 size) we do: + * + * pow = floor(log2(size / len)) = log2(size) - ceil(log2(len)) + */ + pow = ilog2(flash->size) - order_base_2(flash->size - (ofs + len)); + if (ofs + len == flash->size) { + val = 0; /* fully unlocked */ + } else { + val = mask - (pow << shift); + /* Some power-of-two sizes are not supported */ + if (val & ~mask) + return -EINVAL; + } + + status_new = (status_old & ~mask) | val; + + /* Only modify protection if it will not lock other areas */ + if ((status_new & mask) >= (status_old & mask)) + return -EINVAL; + + write_sr(flash, status_new); + + return 0; + } + #endif + + + #ifdef CONFIG_SPI_FLASH_MACRONIX + static int spi_flash_set_qeb_mxic(struct spi_flash *flash) + { + u8 qeb_status; ++#ifdef CONFIG_SPI_GENERIC ++ u8 qeb_status_up; ++#endif + int ret; + ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_LOWER; ++#endif ++ + ret = read_sr(flash, &qeb_status); + if (ret < 0) + return ret; + - if (qeb_status & STATUS_QEB_MXIC) { ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) { ++ flash->spi->flags |= SPI_XFER_UPPER; ++ read_sr(flash, &qeb_status_up); ++ } ++#endif ++ ++ if ((qeb_status & STATUS_QEB_MXIC) ++#ifdef CONFIG_SPI_GENERIC ++ && (qeb_status_up & STATUS_QEB_MXIC) ++#endif ++ ) { + debug("SF: mxic: QEB is already set\n"); + } else { + ret = write_sr(flash, STATUS_QEB_MXIC); + if (ret < 0) + return ret; + } + + return ret; + } + #endif + + #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + static int spi_flash_set_qeb_winspan(struct spi_flash *flash) + { + u8 qeb_status; ++#ifdef CONFIG_SPI_GENERIC ++ u8 qeb_status_up; ++#endif + int ret; + ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_LOWER; ++#endif ++ + ret = read_cr(flash, &qeb_status); + if (ret < 0) + return ret; + - if (qeb_status & STATUS_QEB_WINSPAN) { ++#ifdef CONFIG_SPI_GENERIC ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) { ++ flash->spi->flags |= SPI_XFER_UPPER; ++ ret = read_cr(flash, &qeb_status_up); ++ } ++#endif ++ ++ if ((qeb_status & STATUS_QEB_WINSPAN) ++#ifdef CONFIG_SPI_GENERIC ++ && (qeb_status_up & STATUS_QEB_WINSPAN) ++#endif ++ ) { + debug("SF: winspan: QEB is already set\n"); + } else { + ret = write_cr(flash, STATUS_QEB_WINSPAN); + if (ret < 0) + return ret; + } + + return ret; + } + #endif + + static int spi_flash_set_qeb(struct spi_flash *flash, u8 idcode0) + { + switch (idcode0) { + #ifdef CONFIG_SPI_FLASH_MACRONIX + case SPI_FLASH_CFI_MFR_MACRONIX: + return spi_flash_set_qeb_mxic(flash); + #endif + #if defined(CONFIG_SPI_FLASH_SPANSION) || defined(CONFIG_SPI_FLASH_WINBOND) + case SPI_FLASH_CFI_MFR_SPANSION: + case SPI_FLASH_CFI_MFR_WINBOND: + return spi_flash_set_qeb_winspan(flash); + #endif + #ifdef CONFIG_SPI_FLASH_STMICRO + case SPI_FLASH_CFI_MFR_STMICRO: + debug("SF: QEB is volatile for %02x flash\n", idcode0); + return 0; + #endif + default: + printf("SF: Need set QEB func for %02x flash\n", idcode0); + return -1; + } + } + ++int spi_flash_cmd_4B_addr_switch(struct spi_flash *flash, ++ int enable, u8 idcode0) ++{ ++ int ret; ++ u8 cmd, bar; ++ bool need_wren = false; ++ ++ ret = spi_claim_bus(flash->spi); ++ if (ret) { ++ debug("SF: unable to claim SPI bus\n"); ++ return ret; ++ } ++ ++ switch (idcode0) { ++ case SPI_FLASH_CFI_MFR_STMICRO: ++ /* Some Micron need WREN command; all will accept it */ ++ need_wren = true; ++ case SPI_FLASH_CFI_MFR_MACRONIX: ++ case SPI_FLASH_CFI_MFR_WINBOND: ++ if (need_wren) ++ spi_flash_cmd_write_enable(flash); ++ ++ cmd = enable ? CMD_ENTER_4B_ADDR : CMD_EXIT_4B_ADDR; ++ ret = spi_flash_cmd(flash->spi, cmd, NULL, 0); ++ if (need_wren) ++ spi_flash_cmd_write_disable(flash); ++ ++ break; ++ default: ++ /* Spansion style */ ++ bar = enable << 7; ++ cmd = CMD_BANKADDR_BRWR; ++ ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &bar, 1); ++ } ++ ++ spi_release_bus(flash->spi); ++ ++ return ret; ++} ++ + #if CONFIG_IS_ENABLED(OF_CONTROL) + int spi_flash_decode_fdt(const void *blob, struct spi_flash *flash) + { + fdt_addr_t addr; + fdt_size_t size; + int node; + + /* If there is no node, do nothing */ + node = fdtdec_next_compatible(blob, 0, COMPAT_GENERIC_SPI_FLASH); + if (node < 0) + return 0; + + addr = fdtdec_get_addr_size(blob, node, "memory-map", &size); + if (addr == FDT_ADDR_T_NONE) { + debug("%s: Cannot decode address\n", __func__); + return 0; + } + + if (flash->size != size) { + debug("%s: Memory map must cover entire device\n", __func__); + return -1; + } + flash->memory_map = map_sysmem(addr, size); + + return 0; + } + #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */ + + int spi_flash_scan(struct spi_flash *flash) + { + struct spi_slave *spi = flash->spi; + const struct spi_flash_params *params; + u16 jedec, ext_jedec; - u8 idcode[5]; ++ u8 idcode[6]; ++#ifdef CONFIG_SPI_GENERIC ++ u8 idcode_up[6]; ++ u8 i; ++#endif + u8 cmd; + int ret; + ++#ifdef CONFIG_SPI_GENERIC ++ if (spi->option & SF_DUAL_PARALLEL_FLASH) ++ flash->spi->flags |= SPI_XFER_LOWER; ++#endif ++ + /* Read the ID codes */ + ret = spi_flash_cmd(spi, CMD_READ_ID, idcode, sizeof(idcode)); + if (ret) { + printf("SF: Failed to get idcodes\n"); + return -EINVAL; + } + ++#ifdef CONFIG_SPI_GENERIC ++ if (spi->option == SF_DUAL_PARALLEL_FLASH) { ++ spi->flags |= SPI_XFER_UPPER; ++ ret = spi_flash_cmd(spi, CMD_READ_ID, idcode_up, ++ sizeof(idcode_up)); ++ if (ret) { ++ printf("SF: Failed to get idcodes\n"); ++ return -EINVAL; ++ } ++ for (i = 0; i < sizeof(idcode); i++) { ++ if (idcode[i] != idcode_up[i]) { ++ printf("SF: Failed to get same idcodes\n"); ++ return -EINVAL; ++ } ++ } ++ } ++#endif ++ + #ifdef DEBUG + printf("SF: Got idcodes\n"); + print_buffer(0, idcode, 1, sizeof(idcode), 0); + #endif + + jedec = idcode[1] << 8 | idcode[2]; + ext_jedec = idcode[3] << 8 | idcode[4]; + + /* Validate params from spi_flash_params table */ + params = spi_flash_params_table; + for (; params->name != NULL; params++) { + if ((params->jedec >> 16) == idcode[0]) { + if ((params->jedec & 0xFFFF) == jedec) { + if (params->ext_jedec == 0) + break; + else if (params->ext_jedec == ext_jedec) + break; + } + } + } + + if (!params->name) { + printf("SF: Unsupported flash IDs: "); + printf("manuf %02x, jedec %04x, ext_jedec %04x\n", + idcode[0], jedec, ext_jedec); + return -EPROTONOSUPPORT; + } + + /* Flash powers up read-only, so clear BP# bits */ + if (idcode[0] == SPI_FLASH_CFI_MFR_ATMEL || + idcode[0] == SPI_FLASH_CFI_MFR_MACRONIX || + idcode[0] == SPI_FLASH_CFI_MFR_SST) + write_sr(flash, 0); + + /* Assign spi data */ + flash->name = params->name; + flash->memory_map = spi->memory_map; + flash->dual_flash = flash->spi->option; + + /* Assign spi flash flags */ + if (params->flags & SST_WR) + flash->flags |= SNOR_F_SST_WR; + + /* Assign spi_flash ops */ + #ifndef CONFIG_DM_SPI_FLASH + flash->write = spi_flash_cmd_write_ops; + #if defined(CONFIG_SPI_FLASH_SST) + if (flash->flags & SNOR_F_SST_WR) { + if (flash->spi->op_mode_tx & SPI_OPM_TX_BP) + flash->write = sst_write_bp; + else + flash->write = sst_write_wp; + } + #endif + flash->erase = spi_flash_cmd_erase_ops; + flash->read = spi_flash_cmd_read_ops; + #endif + + /* lock hooks are flash specific - assign them based on idcode0 */ + switch (idcode[0]) { + #if defined(CONFIG_SPI_FLASH_STMICRO) || defined(CONFIG_SPI_FLASH_SST) + case SPI_FLASH_CFI_MFR_STMICRO: + case SPI_FLASH_CFI_MFR_SST: + flash->flash_lock = stm_lock; + flash->flash_unlock = stm_unlock; + flash->flash_is_locked = stm_is_locked; + #endif + break; + default: + debug("SF: Lock ops not supported for %02x flash\n", idcode[0]); + } + + /* Compute the flash size */ + flash->shift = (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ? 1 : 0; + /* + * The Spansion S25FL032P and S25FL064P have 256b pages, yet use the + * 0x4d00 Extended JEDEC code. The rest of the Spansion flashes with + * the 0x4d00 Extended JEDEC code have 512b pages. All of the others + * have 256b pages. + */ + if (ext_jedec == 0x4d00) { + if ((jedec == 0x0215) || (jedec == 0x216)) + flash->page_size = 256; + else + flash->page_size = 512; + } else { + flash->page_size = 256; + } + flash->page_size <<= flash->shift; + flash->sector_size = params->sector_size << flash->shift; - flash->size = flash->sector_size * params->nr_sectors << flash->shift; ++ flash->size = flash->sector_size * params->nr_sectors; ++ ++ /* ++ * So far, the 4-byte address mode haven't been supported in U-Boot, ++ * and make sure the chip (> 16MiB) in default 3-byte address mode, ++ * in case of warm bootup, the chip was set to 4-byte mode in kernel. ++ */ ++ if ((flash->size >> flash->shift) > SPI_FLASH_16MB_BOUN) { ++ if (flash->spi->bytemode == SPI_4BYTE_MODE) { ++ if (spi_flash_cmd_4B_addr_switch(flash, true, ++ idcode[0]) < 0) ++ printf("SF: enter 4B address mode failed\n"); ++ } else { ++ if (spi_flash_cmd_4B_addr_switch(flash, false, ++ idcode[0]) < 0) ++ printf("SF: enter 3B address mode failed\n"); ++ } ++ } else { ++ /* ++ * Clear the 4-byte support if the flash size is ++ * less than 16MB ++ */ ++ if (flash->spi->bytemode == SPI_4BYTE_MODE) ++ flash->spi->bytemode = 0; ++ } ++ + #ifdef CONFIG_SF_DUAL_FLASH + if (flash->dual_flash & SF_DUAL_STACKED_FLASH) + flash->size <<= 1; + #endif + + /* Compute erase sector and command */ + if (params->flags & SECT_4K) { + flash->erase_cmd = CMD_ERASE_4K; + flash->erase_size = 4096 << flash->shift; + } else if (params->flags & SECT_32K) { + flash->erase_cmd = CMD_ERASE_32K; + flash->erase_size = 32768 << flash->shift; + } else { + flash->erase_cmd = CMD_ERASE_64K; + flash->erase_size = flash->sector_size; + } + + /* Now erase size becomes valid sector size */ + flash->sector_size = flash->erase_size; + + /* Look for the fastest read cmd */ + cmd = fls(params->e_rd_cmd & flash->spi->op_mode_rx); + if (cmd) { - cmd = spi_read_cmds_array[cmd - 1]; - flash->read_cmd = cmd; ++ if (flash->spi->dio != SF_DUALIO_FLASH) { ++ if ((idcode[0] == SPI_FLASH_CFI_MFR_SPANSION) && ++ (idcode[5] == SPI_FLASH_SPANSION_S25FS_FMLY)) { ++ flash->read_cmd = CMD_READ_QUAD_IO_FAST; ++ } else { ++ cmd = spi_read_cmds_array[cmd - 1]; ++ flash->read_cmd = cmd; ++ } ++ } else { ++ flash->read_cmd = CMD_READ_DUAL_IO_FAST; ++ } + } else { - /* Go for default supported read cmd */ - flash->read_cmd = CMD_READ_ARRAY_FAST; ++ if (idcode[0] == SPI_FLASH_CFI_MFR_ISSI) ++ flash->read_cmd = CMD_READ_QUAD_IO_FAST; ++ else ++ /* Go for default supported read cmd */ ++ flash->read_cmd = CMD_READ_ARRAY_FAST; + } + + /* Not require to look for fastest only two write cmds yet */ - if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP) - flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; - else ++ if ((params->flags & WR_QPP) && ++ (flash->spi->op_mode_tx & SPI_OPM_TX_QPP) && ++ (flash->spi->dio != SF_DUALIO_FLASH)) { ++ if ((idcode[0] == SPI_FLASH_CFI_MFR_SPANSION) && ++ (idcode[5] == SPI_FLASH_SPANSION_S25FS_FMLY)) ++ flash->write_cmd = CMD_PAGE_PROGRAM; ++ else ++ flash->write_cmd = CMD_QUAD_PAGE_PROGRAM; ++ } else { + /* Go for default supported write cmd */ + flash->write_cmd = CMD_PAGE_PROGRAM; ++ } + + /* Set the quad enable bit - only for quad commands */ + if ((flash->read_cmd == CMD_READ_QUAD_OUTPUT_FAST) || + (flash->read_cmd == CMD_READ_QUAD_IO_FAST) || + (flash->write_cmd == CMD_QUAD_PAGE_PROGRAM)) { - ret = spi_flash_set_qeb(flash, idcode[0]); - if (ret) { ++ if (spi_flash_set_qeb(flash, idcode[0])) { + debug("SF: Fail to set QEB for %02x\n", idcode[0]); - return -EINVAL; ++ return 0; + } ++#ifdef CONFIG_SF_DUAL_FLASH ++ if (flash->dual_flash & SF_DUAL_STACKED_FLASH) { ++ flash->spi->flags |= SPI_XFER_U_PAGE; ++ if (spi_flash_set_qeb(flash, idcode[0])) { ++ debug("SF: Fail to set QEB Upper Flash %02x\n", ++ idcode[0]); ++ return 0; ++ } ++ flash->spi->flags &= ~SPI_XFER_U_PAGE; ++ } ++#endif + } + + /* Read dummy_byte: dummy byte is determined based on the + * dummy cycles of a particular command. + * Fast commands - dummy_byte = dummy_cycles/8 + * I/O commands- dummy_byte = (dummy_cycles * no.of lines)/8 + * For I/O commands except cmd[0] everything goes on no.of lines + * based on particular command but incase of fast commands except + * data all go on single line irrespective of command. + */ + switch (flash->read_cmd) { + case CMD_READ_QUAD_IO_FAST: ++ if (idcode[0] == SPI_FLASH_CFI_MFR_ISSI) ++ flash->dummy_byte = 3; ++ else if ((idcode[0] == SPI_FLASH_CFI_MFR_SPANSION) && ++ (idcode[5] == SPI_FLASH_SPANSION_S25FS_FMLY)) ++ if (flash->dual_flash & SF_DUAL_PARALLEL_FLASH) ++ flash->dummy_byte = 7; ++ else ++ flash->dummy_byte = 5; ++ else + flash->dummy_byte = 2; + break; + case CMD_READ_ARRAY_SLOW: + flash->dummy_byte = 0; + break; + default: + flash->dummy_byte = 1; + } + + #ifdef CONFIG_SPI_FLASH_STMICRO + if (params->flags & E_FSR) + flash->flags |= SNOR_F_USE_FSR; + #endif + + /* Configure the BAR - discover bank cmds and read current bank */ + #ifdef CONFIG_SPI_FLASH_BAR + ret = spi_flash_read_bar(flash, idcode[0]); + if (ret < 0) + return ret; + #endif + + #if CONFIG_IS_ENABLED(OF_CONTROL) + ret = spi_flash_decode_fdt(gd->fdt_blob, flash); + if (ret) { + debug("SF: FDT decode error\n"); + return -EINVAL; + } + #endif + + #ifndef CONFIG_SPL_BUILD + printf("SF: Detected %s with page size ", flash->name); + print_size(flash->page_size, ", erase size "); + print_size(flash->erase_size, ", total "); + print_size(flash->size, ""); + if (flash->memory_map) + printf(", mapped at %p", flash->memory_map); + puts("\n"); + #endif + + #ifndef CONFIG_SPI_FLASH_BAR + if (((flash->dual_flash == SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN)) || + ((flash->dual_flash > SF_SINGLE_FLASH) && + (flash->size > SPI_FLASH_16MB_BOUN << 1))) { + puts("SF: Warning - Only lower 16MiB accessible,"); + puts(" Full access #define CONFIG_SPI_FLASH_BAR\n"); + } + #endif + + return ret; + } diff --cc drivers/net/phy/ti.c index a3956304d09,541a57f9802..5e91c4e3a24 --- a/drivers/net/phy/ti.c +++ b/drivers/net/phy/ti.c @@@ -36,13 -36,11 +36,13 @@@ #define MII_DP83867_MICR_JABBER_INT_EN BIT(0) /* RGMIICTL bits */ - #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) - #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) + #define DP83867_RGMII_TX_CLK_DELAY_EN BIT(1) + #define DP83867_RGMII_RX_CLK_DELAY_EN BIT(0) /* PHY CTRL bits */ - #define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 + #define DP83867_PHYCR_FIFO_DEPTH_SHIFT 14 +#define DP83867_MDI_CROSSOVER 5 +#define DP83867_MDI_CROSSOVER_AUTO 0b10 /* RGMIIDCTL bits */ #define DP83867_RGMII_TX_CLK_DELAY_SHIFT 4 diff --cc drivers/serial/serial_zynq.c index 9d842901966,3430482f8d8..112a7a27b87 --- a/drivers/serial/serial_zynq.c +++ b/drivers/serial/serial_zynq.c @@@ -139,82 -135,80 +135,81 @@@ static int zynq_serial_getc(struct udev return readl(®s->tx_rx_fifo); } - /* Multi serial device functions */ - #define DECLARE_PSSERIAL_FUNCTIONS(port) \ - static int uart_zynq##port##_init(void) \ - { return uart_zynq_serial_init(port); } \ - static void uart_zynq##port##_setbrg(void) \ - { return uart_zynq_serial_setbrg(port); } \ - static int uart_zynq##port##_getc(void) \ - { return uart_zynq_serial_getc(port); } \ - static int uart_zynq##port##_tstc(void) \ - { return uart_zynq_serial_tstc(port); } \ - static void uart_zynq##port##_putc(const char c) \ - { uart_zynq_serial_putc(c, port); } \ - static void uart_zynq##port##_puts(const char *s) \ - { uart_zynq_serial_puts(s, port); } - - /* Serial device descriptor */ - #define INIT_PSSERIAL_STRUCTURE(port, __name) { \ - .name = __name, \ - .start = uart_zynq##port##_init, \ - .stop = NULL, \ - .setbrg = uart_zynq##port##_setbrg, \ - .getc = uart_zynq##port##_getc, \ - .tstc = uart_zynq##port##_tstc, \ - .putc = uart_zynq##port##_putc, \ - .puts = uart_zynq##port##_puts, \ - } + static int zynq_serial_putc(struct udevice *dev, const char ch) + { + struct zynq_uart_priv *priv = dev_get_priv(dev); - DECLARE_PSSERIAL_FUNCTIONS(0); - static struct serial_device uart_zynq_serial0_device = - INIT_PSSERIAL_STRUCTURE(0, "ttyPS0"); - DECLARE_PSSERIAL_FUNCTIONS(1); - static struct serial_device uart_zynq_serial1_device = - INIT_PSSERIAL_STRUCTURE(1, "ttyPS1"); + return _uart_zynq_serial_putc(priv->regs, ch); + } - #if CONFIG_IS_ENABLED(OF_CONTROL) - __weak struct serial_device *default_serial_console(void) + static int zynq_serial_pending(struct udevice *dev, bool input) { - const void *blob = gd->fdt_blob; - int node; - unsigned int base_addr; + struct zynq_uart_priv *priv = dev_get_priv(dev); + struct uart_zynq *regs = priv->regs; - node = fdt_path_offset(blob, "serial0"); - if (node < 0) - return NULL; + if (input) + return !(readl(®s->channel_sts) & ZYNQ_UART_SR_RXEMPTY); + else + return !!(readl(®s->channel_sts) & ZYNQ_UART_SR_TXACTIVE); + } - base_addr = fdtdec_get_addr(blob, node, "reg"); - if (base_addr == FDT_ADDR_T_NONE) - return NULL; + static int zynq_serial_ofdata_to_platdata(struct udevice *dev) + { + struct zynq_uart_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; - if (base_addr == ZYNQ_SERIAL_BASEADDR0) - return &uart_zynq_serial0_device; + addr = fdtdec_get_addr(gd->fdt_blob, dev->of_offset, "reg"); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; - if (base_addr == ZYNQ_SERIAL_BASEADDR1) - return &uart_zynq_serial1_device; + priv->regs = (struct uart_zynq *)addr; - return NULL; + return 0; } - #else - __weak struct serial_device *default_serial_console(void) + + static const struct dm_serial_ops zynq_serial_ops = { + .putc = zynq_serial_putc, + .pending = zynq_serial_pending, + .getc = zynq_serial_getc, + .setbrg = zynq_serial_setbrg, + }; + + static const struct udevice_id zynq_serial_ids[] = { + { .compatible = "xlnx,xuartps" }, + { .compatible = "cdns,uart-r1p8" }, ++ { .compatible = "cdns,uart-r1p12" }, + { } + }; + + U_BOOT_DRIVER(serial_zynq) = { + .name = "serial_zynq", + .id = UCLASS_SERIAL, + .of_match = zynq_serial_ids, + .ofdata_to_platdata = zynq_serial_ofdata_to_platdata, + .priv_auto_alloc_size = sizeof(struct zynq_uart_priv), + .probe = zynq_serial_probe, + .ops = &zynq_serial_ops, + .flags = DM_FLAG_PRE_RELOC, + }; + + #ifdef CONFIG_DEBUG_UART_ZYNQ + static inline void _debug_uart_init(void) { - #if defined(CONFIG_ZYNQ_SERIAL_UART0) - if (uart_zynq_ports[0]) - return &uart_zynq_serial0_device; - #endif - #if defined(CONFIG_ZYNQ_SERIAL_UART1) - if (uart_zynq_ports[1]) - return &uart_zynq_serial1_device; - #endif - return NULL; + struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE; + + _uart_zynq_serial_init(regs); + _uart_zynq_serial_setbrg(regs, CONFIG_DEBUG_UART_CLOCK, + CONFIG_BAUDRATE); } - #endif - void zynq_serial_initialize(void) + static inline void _debug_uart_putc(int ch) { - serial_register(&uart_zynq_serial0_device); - serial_register(&uart_zynq_serial1_device); + struct uart_zynq *regs = (struct uart_zynq *)CONFIG_DEBUG_UART_BASE; + + while (_uart_zynq_serial_putc(regs, ch) == -EAGAIN) + WATCHDOG_RESET(); } + + DEBUG_UART_FUNCS + + #endif diff --cc drivers/spi/zynq_qspi.c index de9d752a5b6,b98663c23b2..6fbc4be6742 --- a/drivers/spi/zynq_qspi.c +++ b/drivers/spi/zynq_qspi.c @@@ -196,124 -133,27 +196,124 @@@ static void zynq_qspi_init_hw(struct zy writel(ZYNQ_QSPI_RXFIFO_THRESHOLD, ®s->rxftr); /* Clear the RX FIFO */ - while (readl(®s->isr) & ZYNQ_QSPI_IXR_RXNEMPTY_MASK) + while (readl(®s->isr) & ZYNQ_QSPI_IXR_RXNEMTY_MASK) readl(®s->drxr); - /* Clear Interrupts */ - writel(ZYNQ_QSPI_IXR_ALL_MASK, ®s->isr); + debug("%s is_dual:0x%x, is_dio:0x%x\n", __func__, priv->is_dual, priv->is_dio); + + writel(0x7F, ®s->isr); + config_reg = readl(®s->confr); + config_reg &= ~ZYNQ_QSPI_CONFIG_MSA_MASK; + config_reg |= ZYNQ_QSPI_CONFIG_IFMODE_MASK | + ZYNQ_QSPI_CONFIG_MCS_MASK | ZYNQ_QSPI_CONFIG_PCS_MASK | + ZYNQ_QSPI_CONFIG_FW_MASK | ZYNQ_QSPI_CONFIG_MSTREN_MASK; + if (priv->is_dual == SF_DUAL_STACKED_FLASH) + config_reg |= 0x10; + writel(config_reg, ®s->confr); + + if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) { + if (priv->is_dio == SF_DUALIO_FLASH) + /* Enable two memories on seperate buses */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + ZYNQ_QSPI_LCFG_SEP_BUS_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_DUALIO_CODE), + ®s->lcr); + else + /* Enable two memories on seperate buses */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + ZYNQ_QSPI_LCFG_SEP_BUS_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_QOUT_CODE), + ®s->lcr); + } else if (priv->is_dual == SF_DUAL_STACKED_FLASH) { + if (priv->is_dio == SF_DUALIO_FLASH) + /* Configure two memories on shared bus + * by enabling lower mem */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_DUALIO_CODE), + ®s->lcr); + else + /* Configure two memories on shared bus + * by enabling lower mem */ + writel((ZYNQ_QSPI_LCFG_TWO_MEM_MASK | + (1 << ZYNQ_QSPI_LCFG_DUMMY_SHIFT) | + ZYNQ_QSPI_FR_QOUT_CODE), + ®s->lcr); + } + writel(ZYNQ_QSPI_ENABLE_ENABLE_MASK, ®s->enbr); +} - /* Manual slave select and Auto start */ - confr = readl(®s->cr); - confr &= ~ZYNQ_QSPI_CR_MSA_MASK; - confr |= ZYNQ_QSPI_CR_IFMODE_MASK | ZYNQ_QSPI_CR_MCS_MASK | - ZYNQ_QSPI_CR_PCS_MASK | ZYNQ_QSPI_CR_FW_MASK | - ZYNQ_QSPI_CR_MSTREN_MASK; - writel(confr, ®s->cr); +/* + * zynq_qspi_check_is_dual_flash - checking for dual or single qspi + * + * This function will check the type of the flash whether it supports + * single or dual qspi based on the MIO configuration done by FSBL. + * + * User needs to correctly configure the MIO's based on the + * number of qspi flashes present on the board. + * + * function will return -1, if there is no MIO configuration for + * qspi flash. + */ +static void zynq_qspi_check_is_dual_flash(struct zynq_qspi_priv *priv) +{ + int lower_mio = 0, upper_mio = 0, upper_mio_cs1 = 0; - /* Disable the LQSPI feature */ - confr = readl(®s->lqspicfg); - confr &= ~ZYNQ_QSPI_LQSPICFG_LQMODE_MASK; - writel(confr, ®s->lqspicfg); + priv->is_dual = -1; + priv->is_dio = 0; + lower_mio = zynq_slcr_get_mio_pin_status("qspi0"); + if (lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0) { + priv->is_dual = SF_SINGLE_FLASH; + } else { + lower_mio = zynq_slcr_get_mio_pin_status("qspi0_dio"); + if (lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0_DIO) { + debug("QSPI in Single 2-bit\n"); + priv->is_dio = SF_DUALIO_FLASH; + priv->is_dual = SF_SINGLE_FLASH; + } + } - /* Enable SPI */ - writel(ZYNQ_QSPI_ENR_SPI_EN_MASK, ®s->enr); + if (priv->is_dio != SF_DUALIO_FLASH) { + upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS)) + priv->is_dual = SF_DUAL_STACKED_FLASH; + + upper_mio = zynq_slcr_get_mio_pin_status("qspi1"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS) && + (upper_mio == ZYNQ_QSPI_MIO_NUM_QSPI1)) + priv->is_dual = SF_DUAL_PARALLEL_FLASH; + } else { + upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs_dio"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0_DIO) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS_DIO)) { + debug("QSPI in DualStacked 2-bit\n"); + priv->is_dual = SF_DUAL_STACKED_FLASH; + } + upper_mio = zynq_slcr_get_mio_pin_status("qspi1_dio"); + if ((lower_mio == ZYNQ_QSPI_MIO_NUM_QSPI0_DIO) && + (upper_mio_cs1 == ZYNQ_QSPI_MIO_NUM_QSPI1_CS_DIO) && + (upper_mio == ZYNQ_QSPI_MIO_NUM_QSPI1_DIO)) { + debug("QSPI in DualParallel 2-bit\n"); + priv->is_dual = SF_DUAL_PARALLEL_FLASH; + } + } +} + +static int zynq_qspi_child_pre_probe(struct udevice *bus) +{ - struct spi_slave *slave = dev_get_parentdata(bus); ++ struct spi_slave *slave = dev_get_parent_priv(bus); + struct zynq_qspi_priv *priv = dev_get_priv(bus->parent); + + slave->option = priv->is_dual; + slave->dio = priv->is_dio; + slave->op_mode_rx = SPI_OPM_RX_QOF; + slave->op_mode_tx = SPI_OPM_TX_QPP; + + return 0; } static int zynq_qspi_probe(struct udevice *bus) diff --cc drivers/spi/zynqmp_qspi.c index 2bac7cd802d,00000000000..fd842a88723 mode 100644,000000..100644 --- a/drivers/spi/zynqmp_qspi.c +++ b/drivers/spi/zynqmp_qspi.c @@@ -1,765 -1,0 +1,765 @@@ +/* + * (C) Copyright 2014 - 2015 Xilinx + * + * Xilinx ZynqMP Quad-SPI(QSPI) controller driver (master mode only) + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../mtd/spi/sf_internal.h" + +#define ZYNQMP_QSPI_GFIFO_STRT_MODE_MASK (1 << 29) +#define ZYNQMP_QSPI_CONFIG_MODE_EN_MASK (3 << 30) +#define ZYNQMP_QSPI_CONFIG_DMA_MODE (2 << 30) +#define ZYNQMP_QSPI_CONFIG_CPHA_MASK (1 << 2) +#define ZYNQMP_QSPI_CONFIG_CPOL_MASK (1 << 1) + +/* QSPI MIO's count for different connection topologies */ +#define ZYNQMP_QSPI_MIO_NUM_QSPI0 6 +#define ZYNQMP_QSPI_MIO_NUM_QSPI1 5 +#define ZYNQMP_QSPI_MIO_NUM_QSPI1_CS 1 + +/* + * QSPI Interrupt Registers bit Masks + * + * All the four interrupt registers (Status/Mask/Enable/Disable) have the same + * bit definitions. + */ +#define ZYNQMP_QSPI_IXR_TXNFULL_MASK 0x00000004 /* QSPI TX FIFO Overflow */ +#define ZYNQMP_QSPI_IXR_TXFULL_MASK 0x00000008 /* QSPI TX FIFO is full */ +#define ZYNQMP_QSPI_IXR_RXNEMTY_MASK 0x00000010 /* QSPI RX FIFO Not Empty */ +#define ZYNQMP_QSPI_IXR_GFEMTY_MASK 0x00000080 /* QSPI Generic FIFO Empty */ +#define ZYNQMP_QSPI_IXR_ALL_MASK (ZYNQMP_QSPI_IXR_TXNFULL_MASK | \ + ZYNQMP_QSPI_IXR_RXNEMTY_MASK) + +/* + * QSPI Enable Register bit Masks + * + * This register is used to enable or disable the QSPI controller + */ +#define ZYNQMP_QSPI_ENABLE_ENABLE_MASK 0x00000001 /* QSPI Enable Bit Mask */ + +#define ZYNQMP_QSPI_GFIFO_LOW_BUS (1 << 14) +#define ZYNQMP_QSPI_GFIFO_CS_LOWER (1 << 12) +#define ZYNQMP_QSPI_GFIFO_UP_BUS (1 << 15) +#define ZYNQMP_QSPI_GFIFO_CS_UPPER (1 << 13) +#define ZYNQMP_QSPI_SPI_MODE_QSPI (3 << 10) +#define ZYNQMP_QSPI_SPI_MODE_SPI (1 << 10) +#define ZYNQMP_QSPI_IMD_DATA_CS_ASSERT 5 +#define ZYNQMP_QSPI_IMD_DATA_CS_DEASSERT 5 +#define ZYNQMP_QSPI_GFIFO_TX (1 << 16) +#define ZYNQMP_QSPI_GFIFO_RX (1 << 17) +#define ZYNQMP_QSPI_GFIFO_STRIPE_MASK (1 << 18) +#define ZYNQMP_QSPI_GFIFO_IMD_MASK 0xFF +#define ZYNQMP_QSPI_GFIFO_EXP_MASK (1 << 9) +#define ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK (1 << 8) +#define ZYNQMP_QSPI_STRT_GEN_FIFO (1 << 28) +#define ZYNQMP_QSPI_GEN_FIFO_STRT_MOD (1 << 29) +#define ZYNQMP_QSPI_GFIFO_WP_HOLD (1 << 19) +#define ZYNQMP_QSPI_BAUD_DIV_MASK (7 << 3) +#define ZYNQMP_QSPI_DFLT_BAUD_RATE_DIV (1 << 3) +#define ZYNQMP_QSPI_GFIFO_ALL_INT_MASK 0xFBE +#define ZYNQMP_QSPI_DMA_DST_I_STS_DONE (1 << 1) +#define ZYNQMP_QSPI_DMA_DST_I_STS_MASK 0xFE +#define MODEBITS 0x6 + +#define QUAD_OUT_READ_CMD 0x6B +#define QUAD_PAGE_PROGRAM_CMD 0x32 + +#define ZYNQMP_QSPI_GFIFO_SELECT (1 << 0) + +#define ZYNQMP_QSPI_FIFO_THRESHOLD 1 + +#define SPI_XFER_ON_BOTH 0 +#define SPI_XFER_ON_LOWER 1 +#define SPI_XFER_ON_UPPER 2 + +#define ZYNQMP_QSPI_DMA_ALIGN 0x4 + +/* QSPI register offsets */ +struct zynqmp_qspi_regs { + u32 confr; /* 0x00 */ + u32 isr; /* 0x04 */ + u32 ier; /* 0x08 */ + u32 idisr; /* 0x0C */ + u32 imaskr; /* 0x10 */ + u32 enbr; /* 0x14 */ + u32 dr; /* 0x18 */ + u32 txd0r; /* 0x1C */ + u32 drxr; /* 0x20 */ + u32 sicr; /* 0x24 */ + u32 txftr; /* 0x28 */ + u32 rxftr; /* 0x2C */ + u32 gpior; /* 0x30 */ + u32 reserved0; /* 0x34 */ + u32 lpbkdly; /* 0x38 */ + u32 reserved1; /* 0x3C */ + u32 genfifo; /* 0x40 */ + u32 gqspisel; /* 0x44 */ + u32 reserved2; /* 0x48 */ + u32 gqfifoctrl; /* 0x4C */ + u32 gqfthr; /* 0x50 */ + u32 gqpollcfg; /* 0x54 */ + u32 gqpollto; /* 0x58 */ + u32 gqxfersts; /* 0x5C */ + u32 gqfifosnap; /* 0x60 */ + u32 gqrxcpy; /* 0x64 */ +}; + +struct zynqmp_qspi_dma_regs { + u32 dmadst; /* 0x00 */ + u32 dmasize; /* 0x04 */ + u32 dmasts; /* 0x08 */ + u32 dmactrl; /* 0x0C */ + u32 reserved0; /* 0x10 */ + u32 dmaisr; /* 0x14 */ + u32 dmaier; /* 0x18 */ + u32 dmaidr; /* 0x1C */ + u32 dmaimr; /* 0x20 */ + u32 dmactrl2; /* 0x24 */ + u32 dmadstmsb; /* 0x28 */ +}; + +struct zynqmp_qspi_platdata { + struct zynqmp_qspi_regs *regs; + struct zynqmp_qspi_dma_regs *dma_regs; + u32 frequency; + u32 speed_hz; +}; + +struct zynqmp_qspi_priv { + struct zynqmp_qspi_regs *regs; + struct zynqmp_qspi_dma_regs *dma_regs; + u8 mode; + u32 freq; + const void *tx_buf; + void *rx_buf; + unsigned len; + int bytes_to_transfer; + int bytes_to_receive; + unsigned int is_inst; + unsigned int is_dual; + unsigned int u_page; + unsigned int bus; + unsigned int stripe; + unsigned cs_change:1; +}; + +static u8 last_cmd; + +static int zynqmp_qspi_ofdata_to_platdata(struct udevice *bus) +{ + struct zynqmp_qspi_platdata *plat = bus->platdata; + + debug("%s\n", __func__); + plat->regs = (struct zynqmp_qspi_regs *)(ZYNQMP_QSPI_BASEADDR + 0x100); + plat->dma_regs = (struct zynqmp_qspi_dma_regs *)(ZYNQMP_QSPI_BASEADDR + + 0x800); + plat->frequency = 166666666; + plat->speed_hz = plat->frequency / 2; + + return 0; +} + +static void zynqmp_qspi_init_hw(struct zynqmp_qspi_priv *priv) +{ + u32 config_reg; + struct zynqmp_qspi_regs *regs = priv->regs; + + writel(ZYNQMP_QSPI_GFIFO_SELECT, ®s->gqspisel); + writel(ZYNQMP_QSPI_GFIFO_ALL_INT_MASK, ®s->idisr); + writel(ZYNQMP_QSPI_FIFO_THRESHOLD, ®s->txftr); + writel(ZYNQMP_QSPI_FIFO_THRESHOLD, ®s->rxftr); + writel(ZYNQMP_QSPI_GFIFO_ALL_INT_MASK, ®s->isr); + + config_reg = readl(®s->confr); + config_reg &= ~(ZYNQMP_QSPI_GFIFO_STRT_MODE_MASK | + ZYNQMP_QSPI_CONFIG_MODE_EN_MASK); + config_reg |= ZYNQMP_QSPI_CONFIG_DMA_MODE | + ZYNQMP_QSPI_GFIFO_WP_HOLD | + ZYNQMP_QSPI_DFLT_BAUD_RATE_DIV; + writel(config_reg, ®s->confr); + + writel(ZYNQMP_QSPI_ENABLE_ENABLE_MASK, ®s->enbr); +} + +static u32 zynqmp_qspi_bus_select(struct zynqmp_qspi_priv *priv) +{ + u32 gqspi_fifo_reg = 0; + + if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) { + if (priv->bus == SPI_XFER_ON_BOTH) + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS | + ZYNQMP_QSPI_GFIFO_UP_BUS | + ZYNQMP_QSPI_GFIFO_CS_UPPER | + ZYNQMP_QSPI_GFIFO_CS_LOWER; + else if (priv->bus == SPI_XFER_ON_LOWER) + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS | + ZYNQMP_QSPI_GFIFO_CS_UPPER | + ZYNQMP_QSPI_GFIFO_CS_LOWER; + else if (priv->bus == SPI_XFER_ON_UPPER) + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS | + ZYNQMP_QSPI_GFIFO_CS_LOWER | + ZYNQMP_QSPI_GFIFO_CS_UPPER; + else + debug("Wrong Bus selection:0x%x\n", priv->bus); + } else { + if (priv->u_page) + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS | + ZYNQMP_QSPI_GFIFO_CS_UPPER; + else + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS | + ZYNQMP_QSPI_GFIFO_CS_LOWER; + } + return gqspi_fifo_reg; +} + +static void zynqmp_qspi_fill_gen_fifo(struct zynqmp_qspi_priv *priv, + u32 gqspi_fifo_reg) +{ + struct zynqmp_qspi_regs *regs = priv->regs; + u32 reg; + + do { + reg = readl(®s->isr); + } while (!(reg & ZYNQMP_QSPI_IXR_GFEMTY_MASK)); + + writel(gqspi_fifo_reg, ®s->genfifo); +} + +static void zynqmp_qspi_chipselect(struct zynqmp_qspi_priv *priv, int is_on) +{ + u32 gqspi_fifo_reg = 0; + + if (is_on) { + gqspi_fifo_reg = zynqmp_qspi_bus_select(priv); + gqspi_fifo_reg |= ZYNQMP_QSPI_SPI_MODE_SPI | + ZYNQMP_QSPI_IMD_DATA_CS_ASSERT; + } else { + if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS | + ZYNQMP_QSPI_GFIFO_LOW_BUS; + else if (priv->u_page) + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_UP_BUS; + else + gqspi_fifo_reg = ZYNQMP_QSPI_GFIFO_LOW_BUS; + gqspi_fifo_reg |= ZYNQMP_QSPI_IMD_DATA_CS_DEASSERT; + } + + debug("GFIFO_CMD_CS: 0x%x\n", gqspi_fifo_reg); + + zynqmp_qspi_fill_gen_fifo(priv, gqspi_fifo_reg); +} + +static int zynqmp_qspi_set_speed(struct udevice *bus, uint speed) +{ + struct zynqmp_qspi_platdata *plat = bus->platdata; + struct zynqmp_qspi_priv *priv = dev_get_priv(bus); + struct zynqmp_qspi_regs *regs = priv->regs; + uint32_t confr; + u8 baud_rate_val = 0; + + debug("%s\n", __func__); + if (speed > plat->frequency) + speed = plat->frequency; + + /* Set the clock frequency */ + confr = readl(®s->confr); + if (speed == 0) { + /* Set baudrate x8, if the freq is 0 */ + baud_rate_val = 0x2; + } else if (plat->speed_hz != speed) { + while ((baud_rate_val < 8) && + ((plat->frequency / + (2 << baud_rate_val)) > speed)) + baud_rate_val++; + + plat->speed_hz = speed / (2 << baud_rate_val); + } + confr &= ~ZYNQMP_QSPI_BAUD_DIV_MASK; + confr |= (baud_rate_val << 3); + writel(confr, ®s->confr); + + priv->freq = speed; + + debug("regs=%p, mode=%d\n", priv->regs, priv->freq); + + return 0; +} + +static int zynqmp_qspi_child_pre_probe(struct udevice *bus) +{ - struct spi_slave *slave = dev_get_parentdata(bus); ++ struct spi_slave *slave = dev_get_parent_priv(bus); + struct zynqmp_qspi_priv *priv = dev_get_priv(bus->parent); + + slave->option = priv->is_dual; + slave->op_mode_rx = SPI_OPM_RX_QOF; + slave->op_mode_tx = SPI_OPM_TX_QPP; + slave->bytemode = SPI_4BYTE_MODE; + + return 0; +} + +static void zynqmp_qspi_check_is_dual_flash(struct zynqmp_qspi_priv *priv) +{ + int lower_mio = 0, upper_mio = 0, upper_mio_cs1 = 0; + + lower_mio = zynq_slcr_get_mio_pin_status("qspi0"); + if (lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0) + priv->is_dual = SF_SINGLE_FLASH; + + upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs"); + if ((lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0) && + (upper_mio_cs1 == ZYNQMP_QSPI_MIO_NUM_QSPI1_CS)) + priv->is_dual = SF_DUAL_STACKED_FLASH; + + upper_mio = zynq_slcr_get_mio_pin_status("qspi1"); + if ((lower_mio == ZYNQMP_QSPI_MIO_NUM_QSPI0) && + (upper_mio_cs1 == ZYNQMP_QSPI_MIO_NUM_QSPI1_CS) && + (upper_mio == ZYNQMP_QSPI_MIO_NUM_QSPI1)) + priv->is_dual = SF_DUAL_PARALLEL_FLASH; +} + +static int zynqmp_qspi_probe(struct udevice *bus) +{ + struct zynqmp_qspi_platdata *plat = dev_get_platdata(bus); + struct zynqmp_qspi_priv *priv = dev_get_priv(bus); + + debug("zynqmp_qspi_probe: bus:%p, priv:%p \n", bus, priv); + + priv->regs = plat->regs; + priv->dma_regs = plat->dma_regs; + zynqmp_qspi_check_is_dual_flash(priv); + + if (priv->is_dual == -1) { + debug("%s: No QSPI device detected based on MIO settings\n", + __func__); + return -1; + } + + /* init the zynq spi hw */ + zynqmp_qspi_init_hw(priv); + + return 0; +} + +static int zynqmp_qspi_set_mode(struct udevice *bus, uint mode) +{ + struct zynqmp_qspi_priv *priv = dev_get_priv(bus); + struct zynqmp_qspi_regs *regs = priv->regs; + uint32_t confr; + + debug("%s\n", __func__); + /* Set the SPI Clock phase and polarities */ + confr = readl(®s->confr); + confr &= ~(ZYNQMP_QSPI_CONFIG_CPHA_MASK | + ZYNQMP_QSPI_CONFIG_CPOL_MASK); + + if (priv->mode & SPI_CPHA) + confr |= ZYNQMP_QSPI_CONFIG_CPHA_MASK; + if (priv->mode & SPI_CPOL) + confr |= ZYNQMP_QSPI_CONFIG_CPOL_MASK; + + //writel(confr, ®s->confr); + priv->mode = mode; + + debug("regs=%p, mode=%d\n", priv->regs, priv->mode); + + return 0; +} + + +static int zynqmp_qspi_fill_tx_fifo(struct zynqmp_qspi_priv *priv, u32 size) +{ + u32 data; + u32 timeout = 10000000; + struct zynqmp_qspi_regs *regs = priv->regs; + u32 *buf = (u32 *)priv->tx_buf; + u32 len = size; + + debug("TxFIFO: 0x%x, size: 0x%x\n", readl(®s->isr), + size); + + while (size && timeout) { + if (readl(®s->isr) & + ZYNQMP_QSPI_IXR_TXNFULL_MASK) { + if (size >= 4) { + writel(*buf, ®s->txd0r); + buf++; + size -= 4; + } else { + switch (size) { + case 1: + data = *((u8 *)buf); + buf += 1; + data |= 0xFFFFFF00; + break; + case 2: + data = *((u16 *)buf); + buf += 2; + data |= 0xFFFF0000; + break; + case 3: + data = *((u16 *)buf); + buf += 2; + data |= (*((u8 *)buf) << 16); + buf += 1; + data |= 0xFF000000; + break; + } + writel(data, ®s->txd0r); + size = 0; + } + } else { + timeout--; + } + } + if (!timeout) { + debug("zynqmp_qspi_fill_tx_fifo: Timeout\n"); + return -1; + } + + priv->tx_buf += len; + return 0; +} + +static void zynqmp_qspi_genfifo_cmd(struct zynqmp_qspi_priv *priv) +{ + u8 command = 1; + u32 gen_fifo_cmd; + u32 bytecount = 0; + + while (priv->len) { + gen_fifo_cmd = zynqmp_qspi_bus_select(priv); + gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_TX; + + if (command) { + command = 0; + last_cmd = *(u8 *)priv->tx_buf; + } + + gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI; + gen_fifo_cmd |= *(u8 *)priv->tx_buf; + bytecount++; + priv->len--; + priv->tx_buf = (u8 *)priv->tx_buf + 1; + + debug("GFIFO_CMD_Cmd = 0x%x\n", gen_fifo_cmd); + + zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); + } +} + +static u32 zynqmp_qspi_calc_exp(struct zynqmp_qspi_priv *priv, + u32 *gen_fifo_cmd) +{ + u32 expval = 8; + u32 len; + + while (1) { + if (priv->len > 255) { + if (priv->len & (1 << expval)) { + *gen_fifo_cmd &= ~ZYNQMP_QSPI_GFIFO_IMD_MASK; + *gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_EXP_MASK; + *gen_fifo_cmd |= expval; + priv->len -= (1 << expval); + return expval; + } + expval++; + } else { + *gen_fifo_cmd &= ~(ZYNQMP_QSPI_GFIFO_IMD_MASK | + ZYNQMP_QSPI_GFIFO_EXP_MASK); + *gen_fifo_cmd |= (u8)priv->len; + len = (u8)priv->len; + priv->len = 0; + return len; + } + } +} + +static int zynqmp_qspi_genfifo_fill_tx(struct zynqmp_qspi_priv *priv) +{ + u32 gen_fifo_cmd; + u32 len; + int ret = 0; + + gen_fifo_cmd = zynqmp_qspi_bus_select(priv); + gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_TX | + ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK; + + if (priv->stripe) + gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK; + + if (last_cmd == QUAD_PAGE_PROGRAM_CMD) + gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_QSPI; + else + gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI; + + while (priv->len) { + len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); + zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); + + debug("GFIFO_CMD_TX:0x%x\n", gen_fifo_cmd); + + if (gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK) + ret = zynqmp_qspi_fill_tx_fifo(priv, + 1 << len); + else + ret = zynqmp_qspi_fill_tx_fifo(priv, + len); + + if (ret) + return ret; + } + return ret; +} + +static int zynqmp_qspi_start_dma(struct zynqmp_qspi_priv *priv, + u32 gen_fifo_cmd, u32 *buf) +{ + u32 addr; + u32 size, len; + u32 timeout = 10000000; + u32 actuallen = priv->len; + struct zynqmp_qspi_dma_regs *dma_regs = priv->dma_regs; + + writel((unsigned long)buf, &dma_regs->dmadst); + writel(roundup(priv->len, 4), &dma_regs->dmasize); + writel(ZYNQMP_QSPI_DMA_DST_I_STS_MASK, &dma_regs->dmaier); + addr = (unsigned long)buf; + size = roundup(priv->len, ARCH_DMA_MINALIGN); + flush_dcache_range(addr, addr+size); + + while (priv->len) { + len = zynqmp_qspi_calc_exp(priv, &gen_fifo_cmd); + if (!(gen_fifo_cmd & ZYNQMP_QSPI_GFIFO_EXP_MASK) && + (len % 4)) { + gen_fifo_cmd &= ~(0xFF); + gen_fifo_cmd |= (len/4 + 1) * 4; + } + zynqmp_qspi_fill_gen_fifo(priv, gen_fifo_cmd); + + debug("GFIFO_CMD_RX:0x%x\n", gen_fifo_cmd); + } + + while (timeout) { + if (readl(&dma_regs->dmaisr) & + ZYNQMP_QSPI_DMA_DST_I_STS_DONE) { + writel(ZYNQMP_QSPI_DMA_DST_I_STS_DONE, + &dma_regs->dmaisr); + break; + } + timeout--; + } + + debug("buf:0x%lx, rxbuf:0x%lx, *buf:0x%x len: 0x%x\n", + (unsigned long)buf, (unsigned long)priv->rx_buf, *buf, + actuallen); + if (!timeout) { + debug("DMA Timeout:0x%x\n", readl(&dma_regs->dmaisr)); + return -1; + } + + if (buf != priv->rx_buf) + memcpy(priv->rx_buf, buf, actuallen); + + return 0; +} + +static int zynqmp_qspi_genfifo_fill_rx(struct zynqmp_qspi_priv *priv) +{ + u32 gen_fifo_cmd; + u32 *buf; + u32 actuallen = priv->len; + + gen_fifo_cmd = zynqmp_qspi_bus_select(priv); + gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_RX | + ZYNQMP_QSPI_GFIFO_DATA_XFR_MASK; + + if (last_cmd == QUAD_OUT_READ_CMD) + gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_QSPI; + else + gen_fifo_cmd |= ZYNQMP_QSPI_SPI_MODE_SPI; + + if (priv->stripe) + gen_fifo_cmd |= ZYNQMP_QSPI_GFIFO_STRIPE_MASK; + + /* + * Check if receive buffer is aligned to 4 byte and length + * is multiples of four byte as we are using dma to receive. + */ + if (!((unsigned long)priv->rx_buf & (ZYNQMP_QSPI_DMA_ALIGN - 1)) && + !(actuallen % ZYNQMP_QSPI_DMA_ALIGN)) { + buf = (u32 *)priv->rx_buf; + return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); + } + + ALLOC_CACHE_ALIGN_BUFFER(u8, tmp, roundup(priv->len, + ZYNQMP_QSPI_DMA_ALIGN)); + buf = (u32 *)tmp; + return zynqmp_qspi_start_dma(priv, gen_fifo_cmd, buf); +} + +static int zynqmp_qspi_start_transfer(struct zynqmp_qspi_priv *priv) +{ + int ret = 0; + + if (priv->is_inst) { + if (priv->tx_buf) + zynqmp_qspi_genfifo_cmd(priv); + else + ret = -1; + } else { + if (priv->tx_buf) + ret = zynqmp_qspi_genfifo_fill_tx(priv); + else if (priv->rx_buf) + ret = zynqmp_qspi_genfifo_fill_rx(priv); + else + ret = -1; + } + return ret; +} + +static int zynqmp_qspi_transfer(struct zynqmp_qspi_priv *priv) +{ + static unsigned cs_change = 1; + int status = 0; + + debug("%s\n", __func__); + + while (1) { + /* Select the chip if required */ + if (cs_change) + zynqmp_qspi_chipselect(priv, 1); + + cs_change = priv->cs_change; + + if (!priv->tx_buf && !priv->rx_buf && priv->len) { + status = -1; + break; + } + + /* Request the transfer */ + if (priv->len) { + status = zynqmp_qspi_start_transfer(priv); + priv->is_inst = 0; + if (status < 0) + break; + } + + if (cs_change) + /* Deselect the chip */ + zynqmp_qspi_chipselect(priv, 0); + break; + } + + return status; +} + +static int zynqmp_qspi_claim_bus(struct udevice *dev) +{ + struct udevice *bus = dev->parent; + struct zynqmp_qspi_priv *priv = dev_get_priv(bus); + struct zynqmp_qspi_regs *regs = priv->regs; + + debug("%s\n", __func__); + writel(ZYNQMP_QSPI_ENABLE_ENABLE_MASK, ®s->enbr); + + return 0; +} + +static int zynqmp_qspi_release_bus(struct udevice *dev) +{ + struct udevice *bus = dev->parent; + struct zynqmp_qspi_priv *priv = dev_get_priv(bus); + struct zynqmp_qspi_regs *regs = priv->regs; + + debug("%s\n", __func__); + writel(~ZYNQMP_QSPI_ENABLE_ENABLE_MASK, ®s->enbr); + + return 0; +} + +int zynqmp_qspi_xfer(struct udevice *dev, unsigned int bitlen, const void *dout, + void *din, unsigned long flags) +{ + struct udevice *bus = dev->parent; + struct zynqmp_qspi_priv *priv = dev_get_priv(bus); + + debug("%s: priv: 0x%08lx bitlen: %d dout: 0x%08lx ", __func__, + (unsigned long)priv, bitlen, (unsigned long)dout); + debug("din: 0x%08lx flags: 0x%lx\n", (unsigned long)din, flags); + + priv->tx_buf = dout; + priv->rx_buf = din; + priv->len = bitlen / 8; + + /* + * Festering sore. + * Assume that the beginning of a transfer with bits to + * transmit must contain a device command. + */ + if (dout && flags & SPI_XFER_BEGIN) + priv->is_inst = 1; + else + priv->is_inst = 0; + + if (flags & SPI_XFER_END) + priv->cs_change = 1; + else + priv->cs_change = 0; + + if (flags & SPI_XFER_U_PAGE) + priv->u_page = 1; + else + priv->u_page = 0; + + priv->stripe = 0; + priv->bus = 0; + + if (priv->is_dual == SF_DUAL_PARALLEL_FLASH) { + if (flags & SPI_XFER_MASK) + priv->bus = (flags & SPI_XFER_MASK) >> 8; + if (flags & SPI_XFER_STRIPE) + priv->stripe = 1; + } + + zynqmp_qspi_transfer(priv); + + return 0; +} + +static const struct dm_spi_ops zynqmp_qspi_ops = { + .claim_bus = zynqmp_qspi_claim_bus, + .release_bus = zynqmp_qspi_release_bus, + .xfer = zynqmp_qspi_xfer, + .set_speed = zynqmp_qspi_set_speed, + .set_mode = zynqmp_qspi_set_mode, +}; + +static const struct udevice_id zynqmp_qspi_ids[] = { + { .compatible = "xlnx,zynqmp-qspi-1.0" }, + { } +}; + +U_BOOT_DRIVER(zynqmp_qspi) = { + .name = "zynqmp_qspi", + .id = UCLASS_SPI, + .of_match = zynqmp_qspi_ids, + .ops = &zynqmp_qspi_ops, + .ofdata_to_platdata = zynqmp_qspi_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct zynqmp_qspi_platdata), + .priv_auto_alloc_size = sizeof(struct zynqmp_qspi_priv), + .probe = zynqmp_qspi_probe, + .child_pre_probe = zynqmp_qspi_child_pre_probe, +}; diff --cc drivers/usb/dwc3/io.h index ddbfb68ce08,0d9fa220e92..8293246a220 --- a/drivers/usb/dwc3/io.h +++ b/drivers/usb/dwc3/io.h @@@ -31,8 -31,7 +31,8 @@@ static inline u32 dwc3_readl(void __iom * space, see dwc3_probe in core.c. * However, the offsets are given starting from xHCI address space. */ - offs += base; - value = readl(offs); - value = readl(base + offs); ++ offs += (unsigned long)base; ++ value = readl((unsigned long)offs); return value; } @@@ -46,8 -45,7 +46,8 @@@ static inline void dwc3_writel(void __i * space, see dwc3_probe in core.c. * However, the offsets are given starting from xHCI address space. */ - offs += base; - writel(value, offs); - writel(value, base + offs); ++ offs += (unsigned long)base; ++ writel(value, (unsigned long)offs); } static inline void dwc3_flush_cache(int addr, int length) diff --cc include/configs/xilinx_zynqmp.h index c3e13721ded,03f74508efe..d250c8db18c --- a/include/configs/xilinx_zynqmp.h +++ b/include/configs/xilinx_zynqmp.h @@@ -138,39 -107,39 +134,39 @@@ #define CONFIG_SYS_LOAD_ADDR 0x8000000 #if defined(CONFIG_ZYNQMP_USB) - # define CONFIG_USB_XHCI_DWC3 - # define CONFIG_USB_XHCI - # define CONFIG_USB_MAX_CONTROLLER_COUNT 1 - # define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 - # define CONFIG_CMD_USB - # define CONFIG_USB_STORAGE - # define CONFIG_USB_XHCI_ZYNQMP - - # define CONFIG_USB_DWC3 - # define CONFIG_USB_DWC3_GADGET - - # define CONFIG_USB_GADGET - # define CONFIG_USB_GADGET_DUALSPEED - # define CONFIG_USB_GADGET_VBUS_DRAW 2 - # define CONFIG_USB_GADGET_DOWNLOAD - # define CONFIG_SYS_DFU_DATA_BUF_SIZE 0x1800000 - # define DFU_DEFAULT_POLL_TIMEOUT 300 - # define CONFIG_DFU_FUNCTION - # define CONFIG_DFU_RAM - # define CONFIG_G_DNL_VENDOR_NUM 0x03FD - # define CONFIG_G_DNL_PRODUCT_NUM 0x0300 - # define CONFIG_G_DNL_MANUFACTURER "Xilinx" - # define CONFIG_USB_CABLE_CHECK - # define CONFIG_CMD_DFU - # define CONFIG_CMD_THOR_DOWNLOAD - # define CONFIG_THOR_RESET_OFF - # define CONFIG_USB_FUNCTION_DFU - # define CONFIG_USB_FUNCTION_THOR - # define DFU_ALT_INFO_RAM \ + #define CONFIG_USB_XHCI_DWC3 + #define CONFIG_USB_XHCI + #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 + #define CONFIG_SYS_USB_XHCI_MAX_ROOT_PORTS 2 + #define CONFIG_CMD_USB + #define CONFIG_USB_STORAGE + #define CONFIG_USB_XHCI_ZYNQMP + + #define CONFIG_USB_DWC3 + #define CONFIG_USB_DWC3_GADGET + + #define CONFIG_USB_GADGET + #define CONFIG_USB_GADGET_DOWNLOAD + #define CONFIG_USB_GADGET_DUALSPEED + #define CONFIG_USB_GADGET_VBUS_DRAW 2 + #define CONFIG_USBDOWNLOAD_GADGET + #define CONFIG_SYS_DFU_DATA_BUF_SIZE 0x1800000 + #define DFU_DEFAULT_POLL_TIMEOUT 300 + #define CONFIG_USB_FUNCTION_DFU + #define CONFIG_DFU_RAM + #define CONFIG_G_DNL_VENDOR_NUM 0x03FD + #define CONFIG_G_DNL_PRODUCT_NUM 0x0300 + #define CONFIG_G_DNL_MANUFACTURER "Xilinx" + #define CONFIG_USB_CABLE_CHECK + #define CONFIG_CMD_DFU + #define CONFIG_CMD_THOR_DOWNLOAD + #define CONFIG_USB_FUNCTION_THOR + #define CONFIG_THOR_RESET_OFF + #define DFU_ALT_INFO_RAM \ "dfu_ram_info=" \ - "set dfu_alt_info " \ - "Image ram 0x200000 0x1800000\\\\;" \ - "system.dtb ram 0x7000000 0x40000\0" \ + "setenv dfu_alt_info " \ + "Image ram $kernel_addr $kernel_size\\\\;" \ + "system.dtb ram $fdt_addr $fdt_size\0" \ "dfu_ram=run dfu_ram_info && dfu 0 ram 0\0" \ "thor_ram=run dfu_ram_info && thordown 0 ram 0\0" @@@ -246,18 -184,12 +242,15 @@@ #define CONFIG_SYS_MAXARGS 64 /* Ethernet driver */ - #if defined(CONFIG_ZYNQ_GEM0) || defined(CONFIG_ZYNQ_GEM1) || \ - defined(CONFIG_ZYNQ_GEM2) || defined(CONFIG_ZYNQ_GEM3) + #if defined(CONFIG_ZYNQ_GEM) # define CONFIG_NET_MULTI - # define CONFIG_ZYNQ_GEM # define CONFIG_MII # define CONFIG_SYS_FAULT_ECHO_LINK_DOWN - # define CONFIG_PHYLIB # define CONFIG_PHY_MARVELL +# define CONFIG_PHY_NATSEMI # define CONFIG_PHY_TI +# define CONFIG_PHY_GIGE +# define PHY_ANEG_TIMEOUT 20000 #endif /* I2C */ diff --cc include/configs/xilinx_zynqmp_ep.h index dccbc388035,ec39211af3d..2cea6a65177 --- a/include/configs/xilinx_zynqmp_ep.h +++ b/include/configs/xilinx_zynqmp_ep.h @@@ -13,32 -15,15 +13,29 @@@ #ifndef __CONFIG_ZYNQMP_EP_H #define __CONFIG_ZYNQMP_EP_H - #define CONFIG_ZYNQ_GEM0 - #define CONFIG_ZYNQ_GEM_PHY_ADDR0 7 - - #define CONFIG_ZYNQ_SERIAL_UART0 #define CONFIG_ZYNQ_SDHCI0 - #define CONFIG_ZYNQ_SDHCI1 #define CONFIG_ZYNQ_SDHCI_MAX_FREQ 52000000 +#define CONFIG_ZYNQ_SDHCI_MIN_FREQ (CONFIG_ZYNQ_SDHCI_MAX_FREQ << 9) #define CONFIG_ZYNQ_I2C0 #define CONFIG_SYS_I2C_ZYNQ #define CONFIG_ZYNQ_EEPROM #define CONFIG_AHCI + #define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR, \ + ZYNQMP_USB1_XHCI_BASEADDR} +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_SDRAM_BASE 0 +#define CONFIG_SYS_SDRAM_SIZE 0x40000000 + +#define COUNTER_FREQUENCY 4000000 + +#define CONFIG_KERNEL_FDT_OFST_SIZE \ + "kernel_offset=0x400000\0" \ + "fdt_offset=0x2400000\0" \ + "kernel_size=0x2000000\0" \ + "fdt_size=0x80000\0" + #include #endif /* __CONFIG_ZYNQMP_EP_H */ diff --cc include/configs/xilinx_zynqmp_zc1751_xm015_dc1.h index daf7b84da50,00000000000..0f258557e69 mode 100644,000000..100644 --- a/include/configs/xilinx_zynqmp_zc1751_xm015_dc1.h +++ b/include/configs/xilinx_zynqmp_zc1751_xm015_dc1.h @@@ -1,38 -1,0 +1,35 @@@ +/* + * Configuration for Xilinx ZynqMP zc1751 XM015 DC1 + * + * (C) Copyright 2015 Xilinx, Inc. + * Michal Simek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_ZYNQMP_ZC1751_XM015_DC1_H +#define __CONFIG_ZYNQMP_ZC1751_XM015_DC1_H + - #define CONFIG_ZYNQ_GEM3 - #define CONFIG_ZYNQ_GEM_PHY_ADDR3 -1 - - #define CONFIG_ZYNQ_SERIAL_UART0 +#define CONFIG_ZYNQ_SDHCI0 +#define CONFIG_ZYNQ_SDHCI1 +#define CONFIG_ZYNQ_I2C1 +#define CONFIG_SYS_I2C_ZYNQ +#define CONFIG_AHCI ++#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR} + +#define CONFIG_IDENT_STRING " Xilinx ZynqMP ZC1751 xm015 dc1" + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_SDRAM_BASE 0 +#define CONFIG_SYS_SDRAM_SIZE 0x80000000 + +#define CONFIG_KERNEL_FDT_OFST_SIZE \ + "kernel_offset=0x400000\0" \ + "fdt_offset=0x2400000\0" \ + "kernel_size=0x2000000\0" \ + "fdt_size=0x80000\0" + +#include + +#endif /* __CONFIG_ZYNQMP_ZC1751_XM015_DC1_H */ diff --cc include/configs/xilinx_zynqmp_zc1751_xm016_dc2.h index 74e75bd3cdd,00000000000..8a3caebd2cc mode 100644,000000..100644 --- a/include/configs/xilinx_zynqmp_zc1751_xm016_dc2.h +++ b/include/configs/xilinx_zynqmp_zc1751_xm016_dc2.h @@@ -1,37 -1,0 +1,32 @@@ +/* + * Configuration for Xilinx ZynqMP zc1751 XM016 DC2 + * + * (C) Copyright 2015 Xilinx, Inc. + * Michal Simek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_ZYNQMP_ZC1751_XM016_DC2_H +#define __CONFIG_ZYNQMP_ZC1751_XM016_DC2_H + - #define CONFIG_ZYNQ_GEM2 - #define CONFIG_ZYNQ_GEM_PHY_ADDR2 -1 - #define CONFIG_ZYNQ_GEM_INTERFACE PHY_INTERFACE_MODE_RGMII_ID - - #define CONFIG_ZYNQ_SERIAL_UART0 - #define CONFIG_ZYNQ_SERIAL_UART1 +#define CONFIG_ZYNQ_I2C0 +#define CONFIG_SYS_I2C_ZYNQ ++#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB1_XHCI_BASEADDR} + +#define CONFIG_IDENT_STRING " Xilinx ZynqMP ZC1751 xm016 dc2" + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_SDRAM_BASE 0 +#define CONFIG_SYS_SDRAM_SIZE 0x80000000 + +#define CONFIG_KERNEL_FDT_OFST_SIZE \ + "kernel_offset=0x400000\0" \ + "fdt_offset=0x2400000\0" \ + "kernel_size=0x2000000\0" \ + "fdt_size=0x80000\0" + +#include + +#endif /* __CONFIG_ZYNQMP_ZC1751_XM016_DC2_H */ diff --cc include/configs/xilinx_zynqmp_zc1751_xm019_dc5.h index d74137ea016,00000000000..7edd5791819 mode 100644,000000..100644 --- a/include/configs/xilinx_zynqmp_zc1751_xm019_dc5.h +++ b/include/configs/xilinx_zynqmp_zc1751_xm019_dc5.h @@@ -1,39 -1,0 +1,34 @@@ +/* + * Configuration for Xilinx ZynqMP zc1751 XM019 DC5 + * + * (C) Copyright 2015 Xilinx, Inc. + * Siva Durga Prasad + * Michal Simek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_ZYNQMP_ZC1751_XM019_DC5_H +#define __CONFIG_ZYNQMP_ZC1751_XM019_DC5_H + - #define CONFIG_ZYNQ_GEM1 - #define CONFIG_ZYNQ_GEM_PHY_ADDR1 -1 - - #define CONFIG_ZYNQ_SERIAL_UART0 - #define CONFIG_ZYNQ_SERIAL_UART1 +#define CONFIG_ZYNQ_SDHCI0 +#define CONFIG_ZYNQ_I2C0 +#define CONFIG_ZYNQ_I2C1 +#define CONFIG_SYS_I2C_ZYNQ + +#define CONFIG_IDENT_STRING " Xilinx ZynqMP ZC1751 xm019 dc5" + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_SDRAM_BASE 0 +#define CONFIG_SYS_SDRAM_SIZE 0x80000000 + +#define CONFIG_KERNEL_FDT_OFST_SIZE \ + "kernel_offset=0x400000\0" \ + "fdt_offset=0x2400000\0" \ + "kernel_size=0x2000000\0" \ + "fdt_size=0x80000\0" + +#include + +#endif /* __CONFIG_ZYNQMP_ZC1751_XM019_DC5_H */ diff --cc include/configs/xilinx_zynqmp_zcu102.h index cf4393b5826,00000000000..42b24927d8a mode 100644,000000..100644 --- a/include/configs/xilinx_zynqmp_zcu102.h +++ b/include/configs/xilinx_zynqmp_zcu102.h @@@ -1,62 -1,0 +1,58 @@@ +/* + * Configuration for Xilinx ZynqMP zcu102 + * + * (C) Copyright 2015 Xilinx, Inc. + * Michal Simek + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __CONFIG_ZYNQMP_ZCU102_H +#define __CONFIG_ZYNQMP_ZCU102_H + - #define CONFIG_ZYNQ_GEM3 - #define CONFIG_ZYNQ_GEM_PHY_ADDR3 -1 - #define CONFIG_ZYNQ_GEM_INTERFACE PHY_INTERFACE_MODE_RGMII_ID - - #define CONFIG_ZYNQ_SERIAL_UART0 +#define CONFIG_ZYNQ_SDHCI1 +#define CONFIG_ZYNQ_I2C0 +#define CONFIG_ZYNQ_I2C1 +#define CONFIG_SYS_I2C_MAX_HOPS 1 +#define CONFIG_SYS_NUM_I2C_BUSES 18 +#define CONFIG_SYS_I2C_BUSES { \ + {0, {I2C_NULL_HOP} }, \ + {0, {{I2C_MUX_PCA9544, 0x75, 0} } }, \ + {0, {{I2C_MUX_PCA9544, 0x75, 1} } }, \ + {0, {{I2C_MUX_PCA9544, 0x75, 2} } }, \ + {1, {I2C_NULL_HOP} }, \ + {1, {{I2C_MUX_PCA9548, 0x74, 0} } }, \ + {1, {{I2C_MUX_PCA9548, 0x74, 1} } }, \ + {1, {{I2C_MUX_PCA9548, 0x74, 2} } }, \ + {1, {{I2C_MUX_PCA9548, 0x74, 3} } }, \ + {1, {{I2C_MUX_PCA9548, 0x74, 4} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 0} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 1} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 2} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 3} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 4} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 5} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 6} } }, \ + {1, {{I2C_MUX_PCA9548, 0x75, 7} } }, \ + } + +#define CONFIG_SYS_I2C_ZYNQ +#define CONFIG_AHCI ++#define CONFIG_ZYNQMP_XHCI_LIST {ZYNQMP_USB0_XHCI_BASEADDR} + +#define CONFIG_IDENT_STRING " Xilinx ZynqMP ZCU102" + +/* Physical Memory Map */ +#define CONFIG_NR_DRAM_BANKS 1 +#define CONFIG_SYS_SDRAM_BASE 0 +#define CONFIG_SYS_SDRAM_SIZE 0x80000000 + +#define CONFIG_KERNEL_FDT_OFST_SIZE \ + "kernel_offset=0x180000\0" \ + "fdt_offset=0x100000\0" \ + "kernel_size=0x1e00000\0" \ + "fdt_size=0x80000\0" + +#include + +#endif /* __CONFIG_ZYNQMP_ZCU102_H */ diff --cc include/configs/zynq-common.h index 7a9ac56802f,0ab60839b6c..4651955de84 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@@ -49,16 -44,12 +44,13 @@@ #endif #define CONFIG_ZYNQ_GPIO - #define CONFIG_CMD_GPIO /* Ethernet driver */ - #if defined(CONFIG_ZYNQ_GEM0) || defined(CONFIG_ZYNQ_GEM1) - # define CONFIG_ZYNQ_GEM + #if defined(CONFIG_ZYNQ_GEM) # define CONFIG_MII # define CONFIG_SYS_FAULT_ECHO_LINK_DOWN - # define CONFIG_PHYLIB # define CONFIG_PHY_MARVELL +# define CONFIG_SYS_ENET # define CONFIG_BOOTP_SERVERIP # define CONFIG_BOOTP_BOOTPATH # define CONFIG_BOOTP_GATEWAY @@@ -74,12 -59,15 +60,19 @@@ /* SPI */ #ifdef CONFIG_ZYNQ_SPI - # define CONFIG_SPI_FLASH_SST + # define CONFIG_CMD_SF #endif - #if defined(CONFIG_ZYNQ_SPI) || defined(CONFIG_ZYNQ_QSPI) - # define CONFIG_CMD_SPI + /* QSPI */ + #ifdef CONFIG_ZYNQ_QSPI + # define CONFIG_SF_DEFAULT_SPEED 30000000 ++# define CONFIG_SPI_FLASH_STMICRO ++# define CONFIG_SPI_FLASH_WINBOND + # define CONFIG_SPI_FLASH_ISSI ++# define CONFIG_SPI_FLASH_MACRONIX + # define CONFIG_SPI_FLASH_BAR # define CONFIG_CMD_SF ++# define CONFIG_SF_DUAL_FLASH #endif /* NOR */ @@@ -181,27 -167,6 +174,16 @@@ # define CONFIG_CMD_FS_GENERIC #endif - /* QSPI */ - #ifdef CONFIG_ZYNQ_QSPI - # define CONFIG_SF_DEFAULT_SPEED 30000000 - # define CONFIG_SPI_FLASH_SPANSION - # define CONFIG_SPI_FLASH_STMICRO - # define CONFIG_SPI_FLASH_WINBOND - # define CONFIG_SPI_FLASH_ISSI - # define CONFIG_SPI_FLASH_MACRONIX - # define CONFIG_SF_DUAL_FLASH - #endif - +/* NAND */ +#ifdef CONFIG_NAND_ZYNQ +# define CONFIG_CMD_NAND +# define CONFIG_CMD_NAND_LOCK_UNLOCK +# define CONFIG_SYS_MAX_NAND_DEVICE 1 +# define CONFIG_SYS_NAND_SELF_INIT +# define CONFIG_SYS_NAND_ONFI_DETECTION +# define CONFIG_MTD_DEVICE +#endif + #if defined(CONFIG_ZYNQ_I2C0) || defined(CONFIG_ZYNQ_I2C1) #define CONFIG_SYS_I2C_ZYNQ #endif @@@ -528,20 -349,14 +509,22 @@@ #define CONFIG_SPL_SPI_LOAD #define CONFIG_SPL_SPI_FLASH_SUPPORT #define CONFIG_SYS_SPI_U_BOOT_OFFS 0x100000 - #endif + #define CONFIG_SYS_SPI_ARGS_OFFS 0x200000 + #define CONFIG_SYS_SPI_ARGS_SIZE 0x80000 + #define CONFIG_SYS_SPI_KERNEL_OFFS (CONFIG_SYS_SPI_ARGS_OFFS + \ + CONFIG_SYS_SPI_ARGS_SIZE) #endif +#ifdef DEBUG +#define CONFIG_SPL_RAM_DEVICE +#define CONFIG_SPL_NET_SUPPORT +#define CONFIG_SPL_ETH_SUPPORT +#define CONFIG_SPL_ENV_SUPPORT +#define CONFIG_SPL_ETH_DEVICE "Gem.e000b000" +#endif + /* for booting directly linux */ #define CONFIG_SPL_OS_BOOT - #define CONFIG_SYS_SPI_KERNEL_OFFS 0 /* FIXME */ /* SP location before relocation, must use scratch RAM */ #define CONFIG_SPL_TEXT_BASE 0x0 diff --cc include/configs/zynq_zc770.h index 309f14e9a0f,32ea1f37d6a..03e620dc7af --- a/include/configs/zynq_zc770.h +++ b/include/configs/zynq_zc770.h @@@ -15,31 -15,15 +15,19 @@@ #define CONFIG_SYS_NO_FLASH #if defined(CONFIG_ZC770_XM010) - # define CONFIG_ZYNQ_SERIAL_UART1 - # define CONFIG_ZYNQ_GEM0 - # define CONFIG_ZYNQ_GEM_PHY_ADDR0 7 # define CONFIG_ZYNQ_SDHCI0 - # define CONFIG_ZYNQ_QSPI +#elif defined(CONFIG_ZC770_XM011) - # define CONFIG_ZYNQ_SERIAL_UART1 +# define CONFIG_NAND_ZYNQ + #elif defined(CONFIG_ZC770_XM011) - # define CONFIG_ZYNQ_SERIAL_UART1 #elif defined(CONFIG_ZC770_XM012) - # define CONFIG_ZYNQ_SERIAL_UART1 # undef CONFIG_SYS_NO_FLASH #elif defined(CONFIG_ZC770_XM013) - # define CONFIG_ZYNQ_SERIAL_UART0 - # define CONFIG_ZYNQ_GEM1 - # define CONFIG_ZYNQ_GEM_PHY_ADDR1 7 +# define CONFIG_ZYNQ_QSPI - #else - # define CONFIG_ZYNQ_SERIAL_UART0 #endif #include diff --cc include/netdev.h index 3d5a54f2aba,de74b9a534b..aa8ec43ecb0 --- a/include/netdev.h +++ b/include/netdev.h @@@ -203,6 -197,6 +197,7 @@@ struct mv88e61xx_config int mv88e61xx_switch_initialize(struct mv88e61xx_config *swconfig); #endif /* CONFIG_MV88E61XX_SWITCH */ ++#ifdef CONFIG_FEC_MXC struct mii_dev *fec_get_miibus(uint32_t base_addr, int dev_id); #ifdef CONFIG_PHYLIB struct phy_device; @@@ -214,5 -208,5 +209,6 @@@ int fec_probe(bd_t *bd, int dev_id, uin */ int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int)); #endif ++#endif #endif /* _NETDEV_H_ */ diff --cc include/spi_flash.h index fc284826eb5,f25b3e7819c..8510d1672e2 --- a/include/spi_flash.h +++ b/include/spi_flash.h @@@ -83,9 -83,7 +85,8 @@@ struct spi_flash u8 bank_read_cmd; u8 bank_write_cmd; u8 bank_curr; + u8 upage_prev; #endif - u8 poll_cmd; u8 erase_cmd; u8 read_cmd; u8 write_cmd; diff --cc scripts/Makefile.spl index e8ce88c6a18,96f414a7afd..eea6e774aba --- a/scripts/Makefile.spl +++ b/scripts/Makefile.spl @@@ -55,8 -56,8 +56,9 @@@ libs-y += common/init libs-$(CONFIG_SPL_LIBCOMMON_SUPPORT) += common/ libs-$(CONFIG_SPL_LIBDISK_SUPPORT) += disk/ libs-y += drivers/ + libs-y += dts/ libs-y += fs/ +libs-$(CONFIG_SPL_FPGA_SUPPORT) += drivers/fpga/ libs-$(CONFIG_SPL_LIBGENERIC_SUPPORT) += lib/ libs-$(CONFIG_SPL_POST_MEM_SUPPORT) += post/drivers/ libs-$(CONFIG_SPL_NET_SUPPORT) += net/