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"
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 \
};
};
+&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>;
};
};
+&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>;
};
};
+&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";
};
};
};
+&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";
};
};
};
+&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";
};
};
};
+&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";
};
#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
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
. = ALIGN(4);
.data : {
*(.data*)
- } > .sram
+ }
. = ALIGN(4);
- } > .sram
+ #ifdef CONFIG_SPL_DM
+ .u_boot_list : {
+ KEEP(*(SORT(.u_boot_list_*_driver_*)));
+ KEEP(*(SORT(.u_boot_list_*_uclass_*)));
++ }
+
+ . = 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);
#include <netdev.h>
#include <ahci.h>
#include <scsi.h>
- #include <usb.h>
+#include <asm/arch/clk.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sys_proto.h>
#include <asm/io.h>
#include <dm.h>
#include <spl.h>
#include <linux/compiler.h>
+ #include <errno.h>
#include <asm/u-boot.h>
+ #include <errno.h>
#include <mmc.h>
#include <image.h>
+#include <fat.h>
+#include <fpga.h>
+#include <xilinx.h>
DECLARE_GLOBAL_DATA_PTR;
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
- void spl_mmc_load_image(void)
+#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
+
+ #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);
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;
}
--- /dev/null
+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
--- /dev/null
- CONFIG_SPI_FLASH_BAR=y
+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
--- /dev/null
- CONFIG_SPI_FLASH_BAR=y
+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
--- /dev/null
- CONFIG_SPI_FLASH_BAR=y
+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
--- /dev/null
- CONFIG_SPI_FLASH_BAR=y
+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_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_SPANSION=y
-CONFIG_SPI_FLASH_STMICRO=y
-CONFIG_SPI_FLASH_WINBOND=y
+ CONFIG_SPI_FLASH=y
+ CONFIG_ZYNQ_GEM=y
+ CONFIG_ZYNQ_QSPI=y
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
--- /dev/null
- # CONFIG_SYS_MALLOC_F is not set
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
- CONFIG_SPI_FLASH_BAR=y
+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_ZYNQ_QSPI=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_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
--- /dev/null
- # CONFIG_SYS_MALLOC_F is not set
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
- CONFIG_SPI_FLASH_BAR=y
+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_ZYNQ_QSPI=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_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
--- /dev/null
- # CONFIG_SYS_MALLOC_F is not set
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
- CONFIG_SPI_FLASH_BAR=y
+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_ZYNQ_QSPI=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_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
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
--- /dev/null
- # CONFIG_SYS_MALLOC_F is not set
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
+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
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
--- /dev/null
- # CONFIG_SYS_MALLOC_F is not set
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
- CONFIG_SPI_FLASH_BAR=y
+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_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_BAR=y
+CONFIG_SPI_FLASH=y
+ CONFIG_ZYNQ_GEM=y
--- /dev/null
- # CONFIG_SYS_MALLOC_F is not set
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
- CONFIG_SPI_FLASH_BAR=y
+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_ZYNQ_QSPI=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_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
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=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
#include <libfdt.h>
#include <malloc.h>
#include <sdhci.h>
- #include <asm/arch/sys_proto.h>
- int zynq_sdhci_init(phys_addr_t regbase)
+#ifndef CONFIG_ZYNQ_SDHCI_MIN_FREQ
+# define CONFIG_ZYNQ_SDHCI_MIN_FREQ 0
+#endif
+
+ 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;
}
#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
#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
return spi_flash_cmd(flash->spi, CMD_WRITE_DISABLE, NULL, 0);
}
- /*
- * 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);
-
+int spi_flash_cmd_bp_unlock(struct spi_flash *flash);
+
/*
* Used for spi_flash write operation
* - SPI claim
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;
}
--- /dev/null
-static void spi_flash_addr(u32 addr, u8 *cmd)
+ /*
+ * SPI Flash Core
+ *
+ * Copyright (C) 2015 Jagan Teki <jteki@openedev.com>
+ * 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 <common.h>
+ #include <errno.h>
+ #include <malloc.h>
+ #include <mapmem.h>
+ #include <spi.h>
+ #include <spi_flash.h>
+ #include <linux/log2.h>
+
+ #include "sf_internal.h"
+
+ DECLARE_GLOBAL_DATA_PTR;
+
- cmd[1] = addr >> 16;
- cmd[2] = addr >> 8;
- cmd[3] = addr >> 0;
++static void spi_flash_addr(u32 addr, u8 *cmd, u8 four_byte)
+ {
+ /* cmd[0] is actual command */
- u8 cmd, bank_sel;
++ 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)
+ {
- if (bank_sel == flash->bank_curr)
- goto bar_end;
++ u8 cmd, bank_sel, upage_curr;
+ int ret;
+
+ bank_sel = offset / (SPI_FLASH_16MB_BOUN << flash->shift);
- ret = read_sr(flash, &sr);
- if (ret < 0)
- return ret;
++
++ 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
+
- return !(sr & STATUS_WIP);
++#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;
+
-
++ 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;
- u32 erase_size, erase_addr;
- u8 cmd[SPI_FLASH_CMD_LEN];
+ 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)
+ {
- ret = spi_flash_write_bar(flash, erase_addr);
- if (ret < 0)
- return ret;
++ 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
- spi_flash_addr(erase_addr, cmd);
++ ret = spi_flash_write_bar(flash, bank_addr);
++ if (ret < 0)
++ return ret;
+ #endif
- ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0);
++ 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);
+
- u32 write_addr;
++#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;
- u8 cmd[SPI_FLASH_CMD_LEN];
++ u32 write_addr, bank_addr;
+ size_t chunk_len, actual;
- ret = spi_flash_write_bar(flash, write_addr);
- if (ret < 0)
- return ret;
++ 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
- spi_flash_addr(write_addr, cmd);
++ 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);
+
- ret = spi_flash_write_common(flash, cmd, sizeof(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);
+
- u32 remain_len, read_len, read_addr;
++#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;
- ret = spi_flash_write_bar(flash, read_addr);
- if (ret < 0)
- return ret;
- bank_sel = flash->bank_curr;
++ 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
- remain_len = ((SPI_FLASH_16MB_BOUN << flash->shift) *
- (bank_sel + 1)) - offset;
- if (len < remain_len)
++ 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
- else
- read_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;
- spi_flash_addr(read_addr, cmd);
++ }
+
- if (qeb_status & STATUS_QEB_MXIC) {
++ 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_WINSPAN) {
++#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;
+
- u8 idcode[5];
++#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;
- flash->size = flash->sector_size * params->nr_sectors << flash->shift;
++ 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;
- cmd = spi_read_cmds_array[cmd - 1];
- flash->read_cmd = cmd;
++ 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) {
- /* Go for default supported read cmd */
- flash->read_cmd = CMD_READ_ARRAY_FAST;
++ 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 {
- if (params->flags & WR_QPP && flash->spi->op_mode_tx & SPI_OPM_TX_QPP)
- flash->write_cmd = CMD_QUAD_PAGE_PROGRAM;
- else
++ 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 */
- ret = spi_flash_set_qeb(flash, idcode[0]);
- if (ret) {
++ 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)) {
- return -EINVAL;
++ if (spi_flash_set_qeb(flash, idcode[0])) {
+ debug("SF: Fail to set QEB for %02x\n", idcode[0]);
++ 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;
+ }
#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
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
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)
--- /dev/null
- struct spi_slave *slave = dev_get_parentdata(bus);
+/*
+ * (C) Copyright 2014 - 2015 Xilinx
+ *
+ * Xilinx ZynqMP Quad-SPI(QSPI) controller driver (master mode only)
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <ubi_uboot.h>
+#include <spi.h>
+#include <spi_flash.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/arch/clk.h>
+#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_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,
+};
* 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;
}
* 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)
#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"
#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 */
#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 <configs/xilinx_zynqmp.h>
#endif /* __CONFIG_ZYNQMP_EP_H */
--- /dev/null
- #define CONFIG_ZYNQ_GEM3
- #define CONFIG_ZYNQ_GEM_PHY_ADDR3 -1
-
- #define CONFIG_ZYNQ_SERIAL_UART0
+/*
+ * Configuration for Xilinx ZynqMP zc1751 XM015 DC1
+ *
+ * (C) Copyright 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_ZYNQMP_ZC1751_XM015_DC1_H
+#define __CONFIG_ZYNQMP_ZC1751_XM015_DC1_H
+
+#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 <configs/xilinx_zynqmp.h>
+
+#endif /* __CONFIG_ZYNQMP_ZC1751_XM015_DC1_H */
--- /dev/null
- #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
+/*
+ * Configuration for Xilinx ZynqMP zc1751 XM016 DC2
+ *
+ * (C) Copyright 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_ZYNQMP_ZC1751_XM016_DC2_H
+#define __CONFIG_ZYNQMP_ZC1751_XM016_DC2_H
+
+#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 <configs/xilinx_zynqmp.h>
+
+#endif /* __CONFIG_ZYNQMP_ZC1751_XM016_DC2_H */
--- /dev/null
- #define CONFIG_ZYNQ_GEM1
- #define CONFIG_ZYNQ_GEM_PHY_ADDR1 -1
-
- #define CONFIG_ZYNQ_SERIAL_UART0
- #define CONFIG_ZYNQ_SERIAL_UART1
+/*
+ * Configuration for Xilinx ZynqMP zc1751 XM019 DC5
+ *
+ * (C) Copyright 2015 Xilinx, Inc.
+ * Siva Durga Prasad <siva.durga.paladugu@xilinx.com>
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_ZYNQMP_ZC1751_XM019_DC5_H
+#define __CONFIG_ZYNQMP_ZC1751_XM019_DC5_H
+
+#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 <configs/xilinx_zynqmp.h>
+
+#endif /* __CONFIG_ZYNQMP_ZC1751_XM019_DC5_H */
--- /dev/null
- #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
+/*
+ * Configuration for Xilinx ZynqMP zcu102
+ *
+ * (C) Copyright 2015 Xilinx, Inc.
+ * Michal Simek <michal.simek@xilinx.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __CONFIG_ZYNQMP_ZCU102_H
+#define __CONFIG_ZYNQMP_ZCU102_H
+
+#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 <configs/xilinx_zynqmp.h>
+
+#endif /* __CONFIG_ZYNQMP_ZCU102_H */
#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
/* 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 */
# 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
#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
#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
- # define CONFIG_ZYNQ_SERIAL_UART1
+#elif defined(CONFIG_ZC770_XM011)
+# 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 <configs/zynq-common.h>
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;
*/
int fecmxc_register_mii_postcall(struct eth_device *dev, int (*cb)(int));
#endif
++#endif
#endif /* _NETDEV_H_ */
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;
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/