Merge tag 'video-20220314' of https://source.denx.de/u-boot/custodians/u-boot-video
- fix display of the u-boot logo on Apple devices
- convert Nokia RX-51 to CONFIG_DM_VIDEO
diff --git a/Makefile b/Makefile
index f8f3f24..8e2441e 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
VERSION = 2022
PATCHLEVEL = 04
SUBLEVEL =
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc4
NAME =
# *DOCUMENTATION*
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 391a77c..4567c18 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1062,6 +1062,8 @@
select DM_ETH
select DM_GPIO
select DM_I2C if I2C
+ select DM_SPI if SPI
+ select DM_SPI_FLASH if SPI
select DM_KEYBOARD
select DM_MMC if MMC
select DM_SCSI if SCSI
diff --git a/arch/arm/dts/armada-3720-turris-mox.dts b/arch/arm/dts/armada-3720-turris-mox.dts
index 1fc4a30..595b4b5 100644
--- a/arch/arm/dts/armada-3720-turris-mox.dts
+++ b/arch/arm/dts/armada-3720-turris-mox.dts
@@ -139,7 +139,9 @@
/*
* U-Boot port for Turris Mox has a bug which always expects that "ranges" DT property
* contains exactly 2 ranges with 3 (child) address cells, 2 (parent) address cells and
- * 2 size cells and also expects that the second range starts at 16 MB offset. If these
+ * 2 size cells and also expects that the second range starts at 16 MB offset. Also it
+ * expects that first range uses same address for PCI (child) and CPU (parent) cells (so
+ * no remapping) and that this address is the lowest from all specified ranges. If these
* conditions are not met then U-Boot crashes during loading kernel DTB file. PCIe address
* space is 128 MB long, so the best split between MEM and IO is to use fixed 16 MB window
* for IO and the rest 112 MB (64+32+16) for MEM. Controller supports 32-bit IO mapping.
@@ -148,6 +150,9 @@
* https://source.denx.de/u-boot/u-boot/-/commit/cb2ddb291ee6fcbddd6d8f4ff49089dfe580f5d7
* https://source.denx.de/u-boot/u-boot/-/commit/c64ac3b3185aeb3846297ad7391fc6df8ecd73bf
* https://source.denx.de/u-boot/u-boot/-/commit/4a82fca8e330157081fc132a591ebd99ba02ee33
+ * Bug related to requirement of same child and parent addresses for first range is fixed
+ * in U-Boot version 2022.04 by following commit:
+ * https://source.denx.de/u-boot/u-boot/-/commit/1fd54253bca7d43d046bba4853fe5fafd034bc17
*/
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/dts/armada-37xx.dtsi b/arch/arm/dts/armada-37xx.dtsi
index 9fa6457..0bb4f60 100644
--- a/arch/arm/dts/armada-37xx.dtsi
+++ b/arch/arm/dts/armada-37xx.dtsi
@@ -499,7 +499,7 @@
* (totaling 127 MiB) for MEM.
*/
ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x07f00000 /* Port 0 MEM */
- 0x81000000 0 0xeff00000 0 0xeff00000 0 0x00100000>; /* Port 0 IO*/
+ 0x81000000 0 0x00000000 0 0xeff00000 0 0x00100000>; /* Port 0 IO */
interrupt-map-mask = <0 0 0 7>;
interrupt-map = <0 0 0 1 &pcie_intc 0>,
<0 0 0 2 &pcie_intc 1>,
diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
index d1c60d2..73da6b8 100644
--- a/arch/arm/mach-sunxi/Kconfig
+++ b/arch/arm/mach-sunxi/Kconfig
@@ -332,9 +332,6 @@
config MACH_SUN50I
bool "sun50i (Allwinner A64)"
select ARM64
- select SPI
- select DM_SPI if SPI
- select DM_SPI_FLASH
select PHY_SUN4I_USB
select SUN6I_PRCM
select SUNXI_DE2
diff --git a/arch/x86/include/asm/intel_gnvs.h b/arch/x86/include/asm/intel_gnvs.h
index fc743dc..0b69530 100644
--- a/arch/x86/include/asm/intel_gnvs.h
+++ b/arch/x86/include/asm/intel_gnvs.h
@@ -47,7 +47,13 @@
BINF_RW_B = 2
};
-enum {
+/**
+ * enum cros_fw_type_t - Used to indicate Chromium OS firmware type
+ *
+ * Chromium OS uses a region of the GNVS starting at offset 0x100 to store
+ * various bits of information, including the type of firmware being booted
+ */
+enum cros_fw_type_t {
FIRMWARE_TYPE_AUTO_DETECT = -1,
FIRMWARE_TYPE_RECOVERY = 0,
FIRMWARE_TYPE_NORMAL = 1,
diff --git a/board/coreboot/coreboot/MAINTAINERS b/board/coreboot/coreboot/MAINTAINERS
index a05673b..ee12d32 100644
--- a/board/coreboot/coreboot/MAINTAINERS
+++ b/board/coreboot/coreboot/MAINTAINERS
@@ -2,12 +2,12 @@
M: Simon Glass <sjg@chromium.org>
S: Maintained
F: board/coreboot/coreboot/
-F: include/configs/chromebook_link.h
+F: include/configs/coreboot.h
F: configs/coreboot_defconfig
COREBOOT64 BOARD
M: Simon Glass <sjg@chromium.org>
S: Maintained
F: board/coreboot/coreboot/
-F: include/configs/chromebook_link.h
+F: include/configs/coreboot.h
F: configs/coreboot64_defconfig
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 82c52b2..a096159 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -171,21 +171,56 @@
#endif
}
-#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT)
+/*
+ * Try to use the environment from the boot source first.
+ * For MMC, this means a FAT partition on the boot device (SD or eMMC).
+ * If the raw MMC environment is also enabled, this is tried next.
+ * SPI flash falls back to FAT (on SD card).
+ */
enum env_location env_get_location(enum env_operation op, int prio)
{
- switch (prio) {
- case 0:
- return ENVL_FAT;
+ enum env_location boot_loc = ENVL_FAT;
- case 1:
- return ENVL_MMC;
+ gd->env_load_prio = prio;
+ switch (sunxi_get_boot_device()) {
+ case BOOT_DEVICE_MMC1:
+ case BOOT_DEVICE_MMC2:
+ boot_loc = ENVL_FAT;
+ break;
+ case BOOT_DEVICE_NAND:
+ if (IS_ENABLED(CONFIG_ENV_IS_IN_NAND))
+ boot_loc = ENVL_NAND;
+ break;
+ case BOOT_DEVICE_SPI:
+ if (IS_ENABLED(CONFIG_ENV_IS_IN_SPI_FLASH))
+ boot_loc = ENVL_SPI_FLASH;
+ break;
+ case BOOT_DEVICE_BOARD:
+ break;
default:
- return ENVL_UNKNOWN;
+ break;
}
+
+ /* Always try to access the environment on the boot device first. */
+ if (prio == 0)
+ return boot_loc;
+
+ if (prio == 1) {
+ switch (boot_loc) {
+ case ENVL_SPI_FLASH:
+ return ENVL_FAT;
+ case ENVL_FAT:
+ if (IS_ENABLED(CONFIG_ENV_IS_IN_MMC))
+ return ENVL_MMC;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return ENVL_UNKNOWN;
}
-#endif
#ifdef CONFIG_DM_MMC
static void mmc_pinmux_setup(int sdc);
diff --git a/board/ti/j721e/evm.c b/board/ti/j721e/evm.c
index f479197..e6ff54c 100644
--- a/board/ti/j721e/evm.c
+++ b/board/ti/j721e/evm.c
@@ -397,36 +397,34 @@
void configure_serdes_sierra(void)
{
- struct udevice *dev, *lnk_dev;
- struct phy serdes;
+ struct udevice *dev, *link_dev;
+ struct phy link;
int ret, count, i;
+ int link_count = 0;
if (!IS_ENABLED(CONFIG_PHY_CADENCE_SIERRA))
return;
- ret = uclass_get_device_by_driver(UCLASS_PHY,
+ ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_DRIVER_GET(sierra_phy_provider),
&dev);
if (ret)
printf("Sierra init failed:%d\n", ret);
- serdes.dev = dev;
- serdes.id = 0;
-
count = device_get_child_count(dev);
for (i = 0; i < count; i++) {
- ret = device_get_child(dev, i, &lnk_dev);
+ ret = device_get_child(dev, i, &link_dev);
if (ret)
printf("probe of sierra child node %d failed\n", i);
- }
-
- ret = generic_phy_init(&serdes);
- if (ret)
- printf("phy_init failed!!\n");
+ if (link_dev->driver->id == UCLASS_PHY) {
+ link.dev = link_dev;
+ link.id = link_count++;
- ret = generic_phy_power_on(&serdes);
- if (ret)
- printf("phy_power_on failed !!\n");
+ ret = generic_phy_power_on(&link);
+ if (ret)
+ printf("phy_power_on failed !!\n");
+ }
+ }
}
#ifdef CONFIG_BOARD_LATE_INIT
diff --git a/cmd/cls.c b/cmd/cls.c
index eab4e69..bdeb497 100644
--- a/cmd/cls.c
+++ b/cmd/cls.c
@@ -11,17 +11,23 @@
#include <lcd.h>
#include <video.h>
+#define CSI "\x1b["
+
static int do_video_clear(struct cmd_tbl *cmdtp, int flag, int argc,
char *const argv[])
{
-#if defined(CONFIG_DM_VIDEO)
- struct udevice *dev;
+ __maybe_unused struct udevice *dev;
+ /* Send clear screen and home */
+ printf(CSI "2J" CSI "1;1H");
+#if defined(CONFIG_DM_VIDEO)
+#if !defined(CONFIG_VIDEO_ANSI)
if (uclass_first_device_err(UCLASS_VIDEO, &dev))
return CMD_RET_FAILURE;
if (video_clear(dev))
return CMD_RET_FAILURE;
+#endif
#elif defined(CONFIG_CFB_CONSOLE)
video_clear();
#elif defined(CONFIG_LCD)
diff --git a/configs/libretech_all_h3_it_h5_defconfig b/configs/libretech_all_h3_it_h5_defconfig
index 7f0e0be..cb7ffb4 100644
--- a/configs/libretech_all_h3_it_h5_defconfig
+++ b/configs/libretech_all_h3_it_h5_defconfig
@@ -7,9 +7,7 @@
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_XMC=y
CONFIG_SPI=y
-CONFIG_DM_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/libretech_all_h5_cc_h5_defconfig b/configs/libretech_all_h5_cc_h5_defconfig
index 25bfe52..c3aa4b1 100644
--- a/configs/libretech_all_h5_cc_h5_defconfig
+++ b/configs/libretech_all_h5_cc_h5_defconfig
@@ -7,10 +7,8 @@
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
-CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH_XMC=y
CONFIG_SUN8I_EMAC=y
CONFIG_SPI=y
-CONFIG_DM_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/oceanic_5205_5inmfd_defconfig b/configs/oceanic_5205_5inmfd_defconfig
index 9ba115c..7ce63ba 100644
--- a/configs/oceanic_5205_5inmfd_defconfig
+++ b/configs/oceanic_5205_5inmfd_defconfig
@@ -11,5 +11,6 @@
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SUN8I_EMAC=y
+CONFIG_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/orangepi_pc2_defconfig b/configs/orangepi_pc2_defconfig
index 2eaddcf..777af8c 100644
--- a/configs/orangepi_pc2_defconfig
+++ b/configs/orangepi_pc2_defconfig
@@ -11,9 +11,11 @@
CONFIG_SPL_I2C=y
CONFIG_SPL_SYS_I2C_LEGACY=y
CONFIG_SYS_I2C_MVTWSI=y
+CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_SUN8I_EMAC=y
CONFIG_SY8106A_POWER=y
CONFIG_SY8106A_VOUT1_VOLT=1100
+CONFIG_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_MUSB_GADGET=y
diff --git a/configs/orangepi_r1_defconfig b/configs/orangepi_r1_defconfig
index 745451c..4496aa4 100644
--- a/configs/orangepi_r1_defconfig
+++ b/configs/orangepi_r1_defconfig
@@ -8,6 +8,8 @@
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_CONSOLE_MUX=y
+CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SUN8I_EMAC=y
+CONFIG_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/orangepi_win_defconfig b/configs/orangepi_win_defconfig
index 8c2179b..3b78ad7 100644
--- a/configs/orangepi_win_defconfig
+++ b/configs/orangepi_win_defconfig
@@ -7,7 +7,9 @@
CONFIG_MACPWR="PD14"
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPI_FLASH_WINBOND=y
CONFIG_PHY_REALTEK=y
CONFIG_SUN8I_EMAC=y
+CONFIG_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/orangepi_zero2_defconfig b/configs/orangepi_zero2_defconfig
index 22563c8..54faf6a 100644
--- a/configs/orangepi_zero2_defconfig
+++ b/configs/orangepi_zero2_defconfig
@@ -15,5 +15,7 @@
CONFIG_SYS_I2C_MVTWSI=y
CONFIG_SYS_I2C_SLAVE=0x7f
CONFIG_SYS_I2C_SPEED=400000
+CONFIG_SPI_FLASH_MACRONIX=y
CONFIG_PHY_REALTEK=y
CONFIG_SUN8I_EMAC=y
+CONFIG_SPI=y
diff --git a/configs/orangepi_zero_defconfig b/configs/orangepi_zero_defconfig
index 332cd47..2dc69d2 100644
--- a/configs/orangepi_zero_defconfig
+++ b/configs/orangepi_zero_defconfig
@@ -8,6 +8,8 @@
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_CONSOLE_MUX=y
+CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SUN8I_EMAC=y
+CONFIG_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/pine64-lts_defconfig b/configs/pine64-lts_defconfig
index 6209e68..45a9e77 100644
--- a/configs/pine64-lts_defconfig
+++ b/configs/pine64-lts_defconfig
@@ -10,6 +10,8 @@
CONFIG_MMC_SUNXI_SLOT_EXTRA=2
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SUN8I_EMAC=y
+CONFIG_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
index 1928509..1e730dd 100644
--- a/configs/pine_h64_defconfig
+++ b/configs/pine_h64_defconfig
@@ -11,8 +11,10 @@
CONFIG_SPL_SPI_SUNXI=y
# CONFIG_PSCI_RESET is not set
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
+CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SUN8I_EMAC=y
CONFIG_PHY_SUN50I_USB3=y
+CONFIG_SPI=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y
CONFIG_USB_EHCI_HCD=y
diff --git a/configs/pinecube_defconfig b/configs/pinecube_defconfig
index 0c71d59..e779663 100644
--- a/configs/pinecube_defconfig
+++ b/configs/pinecube_defconfig
@@ -12,8 +12,10 @@
CONFIG_SYS_I2C_MVTWSI=y
CONFIG_SYS_I2C_SLAVE=0x7f
CONFIG_SYS_I2C_SPEED=400000
+CONFIG_SPI_FLASH_WINBOND=y
# CONFIG_NETDEVICES is not set
CONFIG_AXP209_POWER=y
CONFIG_AXP_DCDC2_VOLT=1250
CONFIG_AXP_DCDC3_VOLT=3300
CONFIG_CONS_INDEX=3
+CONFIG_SPI=y
diff --git a/configs/sopine_baseboard_defconfig b/configs/sopine_baseboard_defconfig
index 0093076..982f7b0 100644
--- a/configs/sopine_baseboard_defconfig
+++ b/configs/sopine_baseboard_defconfig
@@ -13,5 +13,6 @@
# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
CONFIG_SPI_FLASH_WINBOND=y
CONFIG_SUN8I_EMAC=y
+CONFIG_SPI=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/configs/tbs2910_defconfig b/configs/tbs2910_defconfig
index e1278f2..8a33160 100644
--- a/configs/tbs2910_defconfig
+++ b/configs/tbs2910_defconfig
@@ -14,6 +14,7 @@
CONFIG_PRE_CON_BUF_ADDR=0x7c000000
CONFIG_CMD_HDMIDETECT=y
CONFIG_AHCI=y
+CONFIG_LTO=y
CONFIG_SUPPORT_RAW_INITRD=y
CONFIG_BOOTDELAY=3
CONFIG_USE_BOOTCOMMAND=y
diff --git a/configs/vexpress_aemv8a_semi_defconfig b/configs/vexpress_aemv8a_semi_defconfig
index 82a5b52..448d012 100644
--- a/configs/vexpress_aemv8a_semi_defconfig
+++ b/configs/vexpress_aemv8a_semi_defconfig
@@ -17,7 +17,7 @@
CONFIG_BOOTDELAY=1
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="console=ttyAMA0 earlycon=pl011,0x1c090000 debug user_debug=31 loglevel=9"
-CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then set bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; set fdt_high 0xffffffffffffffff; set initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr - $fdt_addr_r; fi"
+CONFIG_BOOTCOMMAND="if smhload ${boot_name} ${boot_addr_r}; then setenv bootargs; abootimg addr ${boot_addr_r}; abootimg get dtb --index=0 fdt_addr_r; bootm ${boot_addr_r} ${boot_addr_r} ${fdt_addr_r}; else; setenv fdt_high 0xffffffffffffffff; setenv initrd_high 0xffffffffffffffff; smhload ${kernel_name} ${kernel_addr_r}; smhload ${fdtfile} ${fdt_addr_r}; smhload ${ramdisk_name} ${ramdisk_addr_r} ramdisk_end; fdt addr ${fdt_addr_r}; fdt resize; fdt chosen ${ramdisk_addr_r} ${ramdisk_end}; booti $kernel_addr_r - $fdt_addr_r; fi"
# CONFIG_DISPLAY_CPUINFO is not set
# CONFIG_DISPLAY_BOARDINFO is not set
CONFIG_SYS_PROMPT="VExpress64# "
diff --git a/doc/board/sifive/unmatched.rst b/doc/board/sifive/unmatched.rst
index 24a8899..a994422 100644
--- a/doc/board/sifive/unmatched.rst
+++ b/doc/board/sifive/unmatched.rst
@@ -560,7 +560,7 @@
.. code-block:: none
- dd if=u-boot-spl.bin of=/dev/mtdblock0 bs=4096 seek=5 conv=sync
+ dd if=spl/u-boot-spl.bin of=/dev/mtdblock0 bs=4096 seek=5 conv=sync
dd if=u-boot.itb of=/dev/mtdblock0 bs=4096 seek=261 conv=sync
Power off the board.
diff --git a/doc/build/gcc.rst b/doc/build/gcc.rst
index b883cf7..470a7aa 100644
--- a/doc/build/gcc.rst
+++ b/doc/build/gcc.rst
@@ -25,11 +25,12 @@
sudo apt-get install bc bison build-essential coccinelle \
device-tree-compiler dfu-util efitools flex gdisk graphviz imagemagick \
- liblz4-tool libguestfs-tools libncurses-dev libpython3-dev libsdl2-dev \
- libssl-dev lz4 lzma lzma-alone openssl pkg-config python3 \
- python3-coverage python3-pkg-resources python3-pycryptodome \
- python3-pyelftools python3-pytest python3-sphinxcontrib.apidoc \
- python3-sphinx-rtd-theme python3-virtualenv swig
+ liblz4-tool libgnutls28-dev libguestfs-tools libncurses-dev \
+ libpython3-dev libsdl2-dev libssl-dev lz4 lzma lzma-alone openssl \
+ pkg-config python3 python3-coverage python3-pkg-resources \
+ python3-pycryptodome python3-pyelftools python3-pytest \
+ python3-sphinxcontrib.apidoc python3-sphinx-rtd-theme python3-virtualenv \
+ swig
SUSE based
~~~~~~~~~~
diff --git a/drivers/mmc/rockchip_sdhci.c b/drivers/mmc/rockchip_sdhci.c
index 2784738..b91df05 100644
--- a/drivers/mmc/rockchip_sdhci.c
+++ b/drivers/mmc/rockchip_sdhci.c
@@ -90,9 +90,33 @@
};
struct sdhci_data {
- int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
int (*emmc_phy_init)(struct udevice *dev);
int (*get_phy)(struct udevice *dev);
+
+ /**
+ * set_control_reg() - Set SDHCI control registers
+ *
+ * This is the set_control_reg() SDHCI operation that should be
+ * used for the hardware this driver data is associated with.
+ * Normally, this is used to set up control registers for
+ * voltage level and UHS speed mode.
+ *
+ * @host: SDHCI host structure
+ */
+ void (*set_control_reg)(struct sdhci_host *host);
+
+ /**
+ * set_ios_post() - Host specific hook after set_ios() calls
+ *
+ * This is the set_ios_post() SDHCI operation that should be
+ * used for the hardware this driver data is associated with.
+ * Normally, this is a hook that is called after sdhci_set_ios()
+ * that does any necessary host-specific configuration.
+ *
+ * @host: SDHCI host structure
+ * Return: 0 if successful, -ve on error
+ */
+ int (*set_ios_post)(struct sdhci_host *host);
};
static int rk3399_emmc_phy_init(struct udevice *dev)
@@ -182,15 +206,28 @@
return 0;
}
-static int rk3399_sdhci_emmc_set_clock(struct sdhci_host *host, unsigned int clock)
+static void rk3399_sdhci_set_control_reg(struct sdhci_host *host)
{
struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct mmc *mmc = host->mmc;
+ uint clock = mmc->tran_speed;
int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ;
if (cycle_phy)
rk3399_emmc_phy_power_off(priv->phy);
- sdhci_set_clock(host->mmc, clock);
+ sdhci_set_control_reg(host);
+};
+
+static int rk3399_sdhci_set_ios_post(struct sdhci_host *host)
+{
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct mmc *mmc = host->mmc;
+ uint clock = mmc->tran_speed;
+ int cycle_phy = host->clock != clock && clock > EMMC_MIN_FREQ;
+
+ if (!clock)
+ clock = mmc->clock;
if (cycle_phy)
rk3399_emmc_phy_power_on(priv->phy, clock);
@@ -269,10 +306,8 @@
return 0;
}
-static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
+static int rk3568_sdhci_set_ios_post(struct sdhci_host *host)
{
- struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
- struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
struct mmc *mmc = host->mmc;
uint clock = mmc->tran_speed;
u32 reg;
@@ -280,8 +315,7 @@
if (!clock)
clock = mmc->clock;
- if (data->emmc_set_clock)
- data->emmc_set_clock(host, clock);
+ rk3568_sdhci_emmc_set_clock(host, clock);
if (mmc->selected_mode == MMC_HS_400 || mmc->selected_mode == MMC_HS_400_ES) {
reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
@@ -295,6 +329,26 @@
return 0;
}
+static void rockchip_sdhci_set_control_reg(struct sdhci_host *host)
+{
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+ if (data->set_control_reg)
+ data->set_control_reg(host);
+}
+
+static int rockchip_sdhci_set_ios_post(struct sdhci_host *host)
+{
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
+
+ if (data->set_ios_post)
+ return data->set_ios_post(host);
+
+ return 0;
+}
+
static int rockchip_sdhci_execute_tuning(struct mmc *mmc, u8 opcode)
{
struct sdhci_host *host = dev_get_priv(mmc->dev);
@@ -358,6 +412,7 @@
static struct sdhci_ops rockchip_sdhci_ops = {
.set_ios_post = rockchip_sdhci_set_ios_post,
.platform_execute_tuning = &rockchip_sdhci_execute_tuning,
+ .set_control_reg = rockchip_sdhci_set_control_reg,
};
static int rockchip_sdhci_probe(struct udevice *dev)
@@ -436,15 +491,16 @@
}
static const struct sdhci_data rk3399_data = {
- .emmc_set_clock = rk3399_sdhci_emmc_set_clock,
.get_phy = rk3399_emmc_get_phy,
.emmc_phy_init = rk3399_emmc_phy_init,
+ .set_control_reg = rk3399_sdhci_set_control_reg,
+ .set_ios_post = rk3399_sdhci_set_ios_post,
};
static const struct sdhci_data rk3568_data = {
- .emmc_set_clock = rk3568_sdhci_emmc_set_clock,
.get_phy = rk3568_emmc_get_phy,
.emmc_phy_init = rk3568_emmc_phy_init,
+ .set_ios_post = rk3568_sdhci_set_ios_post,
};
static const struct udevice_id sdhci_ids[] = {
diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c
index b551ebd..763bab0 100644
--- a/drivers/mtd/spi/spi-nor-ids.c
+++ b/drivers/mtd/spi/spi-nor-ids.c
@@ -119,7 +119,7 @@
},
{
INFO("gd25lq128", 0xc86018, 0, 64 * 1024, 256,
- SECT_4K | SPI_NOR_DUAL_READ |
+ SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |
SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)
},
{
diff --git a/drivers/phy/cadence/phy-cadence-sierra.c b/drivers/phy/cadence/phy-cadence-sierra.c
index d95d4b4..fc5044f 100644
--- a/drivers/phy/cadence/phy-cadence-sierra.c
+++ b/drivers/phy/cadence/phy-cadence-sierra.c
@@ -358,26 +358,10 @@
return 0;
}
-static inline struct cdns_sierra_inst *phy_get_drvdata(struct phy *phy)
+static int cdns_sierra_link_init(struct phy *gphy)
{
- struct cdns_sierra_phy *sp = dev_get_priv(phy->dev);
- int index;
-
- if (phy->id >= SIERRA_MAX_LANES)
- return NULL;
-
- for (index = 0; index < sp->nsubnodes; index++) {
- if (phy->id == sp->phys[index]->mlane)
- return sp->phys[index];
- }
-
- return NULL;
-}
-
-static int cdns_sierra_phy_init(struct phy *gphy)
-{
- struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
- struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev);
+ struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev);
+ struct cdns_sierra_phy *phy = dev_get_priv(gphy->dev->parent);
struct cdns_sierra_data *init_data = phy->init_data;
struct cdns_sierra_vals *pma_cmn_vals, *pma_ln_vals;
enum cdns_sierra_phy_type phy_type = ins->phy_type;
@@ -443,10 +427,11 @@
return 0;
}
-static int cdns_sierra_phy_on(struct phy *gphy)
+static int cdns_sierra_link_on(struct phy *gphy)
{
- struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
- struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev);
+ struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev);
+ struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent);
+
struct udevice *dev = gphy->dev;
u32 val;
int ret;
@@ -503,16 +488,16 @@
return ret;
}
-static int cdns_sierra_phy_off(struct phy *gphy)
+static int cdns_sierra_link_off(struct phy *gphy)
{
- struct cdns_sierra_inst *ins = phy_get_drvdata(gphy);
+ struct cdns_sierra_inst *ins = dev_get_priv(gphy->dev);
return reset_assert_bulk(ins->lnk_rst);
}
-static int cdns_sierra_phy_reset(struct phy *gphy)
+static int cdns_sierra_link_reset(struct phy *gphy)
{
- struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev);
+ struct cdns_sierra_phy *sp = dev_get_priv(gphy->dev->parent);
reset_control_assert(sp->phy_rst);
reset_control_deassert(sp->phy_rst);
@@ -520,10 +505,10 @@
};
static const struct phy_ops ops = {
- .init = cdns_sierra_phy_init,
- .power_on = cdns_sierra_phy_on,
- .power_off = cdns_sierra_phy_off,
- .reset = cdns_sierra_phy_reset,
+ .init = cdns_sierra_link_init,
+ .power_on = cdns_sierra_link_on,
+ .power_off = cdns_sierra_link_off,
+ .reset = cdns_sierra_link_reset,
};
struct cdns_sierra_pll_mux_sel {
@@ -580,7 +565,7 @@
.set_parent = cdns_sierra_pll_mux_set_parent,
};
-int cdns_sierra_pll_mux_probe(struct udevice *dev)
+static int cdns_sierra_pll_mux_probe(struct udevice *dev)
{
struct cdns_sierra_pll_mux *priv = dev_get_priv(dev);
struct cdns_sierra_phy *sp = dev_get_priv(dev->parent);
@@ -1012,9 +997,8 @@
return 0;
}
-static int cdns_sierra_bind_link_nodes(struct cdns_sierra_phy *sp)
+static int cdns_sierra_phy_bind(struct udevice *dev)
{
- struct udevice *dev = sp->dev;
struct driver *link_drv;
ofnode child;
int rc;
@@ -1079,6 +1063,7 @@
.name = "sierra_phy_link",
.id = UCLASS_PHY,
.probe = cdns_sierra_link_probe,
+ .ops = &ops,
.priv_auto = sizeof(struct cdns_sierra_inst),
};
@@ -1141,10 +1126,6 @@
}
sp->autoconf = dev_read_bool(dev, "cdns,autoconf");
- /* Binding link nodes as children to serdes */
- ret = cdns_sierra_bind_link_nodes(sp);
- if (ret)
- goto clk_disable;
dev_info(dev, "sierra probed\n");
return 0;
@@ -1971,10 +1952,10 @@
U_BOOT_DRIVER(sierra_phy_provider) = {
.name = "cdns,sierra",
- .id = UCLASS_PHY,
+ .id = UCLASS_MISC,
.of_match = cdns_sierra_id_table,
.probe = cdns_sierra_phy_probe,
.remove = cdns_sierra_phy_remove,
- .ops = &ops,
+ .bind = cdns_sierra_phy_bind,
.priv_auto = sizeof(struct cdns_sierra_phy),
};
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 0a6a85f..423a757 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -185,6 +185,12 @@
access the SPI NOR flash on platforms embedding this Intel
ICH IP core.
+config IPROC_QSPI
+ bool "Broadcom iProc QSPI Flash Controller driver"
+ help
+ Enable Broadcom iProc QSPI Flash Controller driver.
+ This driver can be used to access the SPI NOR flash.
+
config KIRKWOOD_SPI
bool "Marvell Kirkwood SPI Driver"
help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index bea746f..7f43f84 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -34,6 +34,7 @@
obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
obj-$(CONFIG_SYNQUACER_SPI) += spi-synquacer.o
obj-$(CONFIG_ICH_SPI) += ich.o
+obj-$(CONFIG_IPROC_QSPI) += iproc_qspi.o
obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
obj-$(CONFIG_MESON_SPIFC) += meson_spifc.o
obj-$(CONFIG_MPC8XX_SPI) += mpc8xx_spi.o
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index d1b3808..db68061 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -201,11 +201,9 @@
}
}
- ret = reset_get_bulk(bus, &priv->resets);
- if (ret)
- dev_warn(bus, "Can't get reset: %d\n", ret);
- else
- reset_deassert_bulk(&priv->resets);
+ priv->resets = devm_reset_bulk_get_optional(bus);
+ if (priv->resets)
+ reset_deassert_bulk(priv->resets);
if (!priv->qspi_is_init) {
cadence_qspi_apb_controller_init(plat);
@@ -220,8 +218,12 @@
static int cadence_spi_remove(struct udevice *dev)
{
struct cadence_spi_priv *priv = dev_get_priv(dev);
+ int ret = 0;
+
+ if (priv->resets)
+ ret = reset_release_bulk(priv->resets);
- return reset_release_bulk(&priv->resets);
+ return ret;
}
static int cadence_spi_set_mode(struct udevice *bus, uint mode)
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 49b4011..19345ca 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -56,7 +56,7 @@
unsigned int qspi_calibrated_cs;
unsigned int previous_hz;
- struct reset_ctl_bulk resets;
+ struct reset_ctl_bulk *resets;
};
/* Functions call declaration */
diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c
index 7421211..fc22f54 100644
--- a/drivers/spi/designware_spi.c
+++ b/drivers/spi/designware_spi.c
@@ -572,7 +572,7 @@
int pos, i, ret = 0;
struct udevice *bus = slave->dev->parent;
struct dw_spi_priv *priv = dev_get_priv(bus);
- u8 op_len = sizeof(op->cmd.opcode) + op->addr.nbytes + op->dummy.nbytes;
+ u8 op_len = op->cmd.nbytes + op->addr.nbytes + op->dummy.nbytes;
u8 op_buf[op_len];
u32 cr0;
diff --git a/drivers/spi/iproc_qspi.c b/drivers/spi/iproc_qspi.c
new file mode 100644
index 0000000..b5c2743
--- /dev/null
+++ b/drivers/spi/iproc_qspi.c
@@ -0,0 +1,576 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020-2021 Broadcom
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <spi.h>
+#include <spi-mem.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/iopoll.h>
+#include <linux/log2.h>
+
+/* Delay required to change the mode of operation */
+#define BUSY_DELAY_US 1
+#define BUSY_TIMEOUT_US 200000
+#define DWORD_ALIGNED(a) (!(((ulong)(a)) & 3))
+
+/* Chip attributes */
+#define QSPI_AXI_CLK 175000000
+#define SPBR_MIN 8U
+#define SPBR_MAX 255U
+#define NUM_CDRAM 16U
+
+#define CDRAM_PCS0 2
+#define CDRAM_CONT BIT(7)
+#define CDRAM_BITS_EN BIT(6)
+#define CDRAM_QUAD_MODE BIT(8)
+#define CDRAM_RBIT_INPUT BIT(10)
+#define MSPI_SPE BIT(6)
+#define MSPI_CONT_AFTER_CMD BIT(7)
+#define MSPI_MSTR BIT(7)
+
+/* Register fields */
+#define MSPI_SPCR0_MSB_BITS_8 0x00000020
+#define BSPI_RAF_CONTROL_START_MASK 0x00000001
+#define BSPI_RAF_STATUS_SESSION_BUSY_MASK 0x00000001
+#define BSPI_RAF_STATUS_FIFO_EMPTY_MASK 0x00000002
+#define BSPI_STRAP_OVERRIDE_DATA_QUAD_SHIFT 3
+#define BSPI_STRAP_OVERRIDE_4BYTE_SHIFT 2
+#define BSPI_STRAP_OVERRIDE_DATA_DUAL_SHIFT 1
+#define BSPI_STRAP_OVERRIDE_SHIFT 0
+#define BSPI_BPC_DATA_SHIFT 0
+#define BSPI_BPC_MODE_SHIFT 8
+#define BSPI_BPC_ADDR_SHIFT 16
+#define BSPI_BPC_CMD_SHIFT 24
+#define BSPI_BPP_ADDR_SHIFT 16
+
+/* MSPI registers */
+#define MSPI_SPCR0_LSB_REG 0x000
+#define MSPI_SPCR0_MSB_REG 0x004
+#define MSPI_SPCR1_LSB_REG 0x008
+#define MSPI_SPCR1_MSB_REG 0x00c
+#define MSPI_NEWQP_REG 0x010
+#define MSPI_ENDQP_REG 0x014
+#define MSPI_SPCR2_REG 0x018
+#define MSPI_STATUS_REG 0x020
+#define MSPI_CPTQP_REG 0x024
+#define MSPI_TX_REG 0x040
+#define MSPI_RX_REG 0x0c0
+#define MSPI_CDRAM_REG 0x140
+#define MSPI_WRITE_LOCK_REG 0x180
+#define MSPI_DISABLE_FLUSH_GEN_REG 0x184
+
+/* BSPI registers */
+#define BSPI_REVISION_ID_REG 0x000
+#define BSPI_SCRATCH_REG 0x004
+#define BSPI_MAST_N_BOOT_CTRL_REG 0x008
+#define BSPI_BUSY_STATUS_REG 0x00c
+#define BSPI_INTR_STATUS_REG 0x010
+#define BSPI_B0_STATUS_REG 0x014
+#define BSPI_B0_CTRL_REG 0x018
+#define BSPI_B1_STATUS_REG 0x01c
+#define BSPI_B1_CTRL_REG 0x020
+#define BSPI_STRAP_OVERRIDE_CTRL_REG 0x024
+#define BSPI_FLEX_MODE_ENABLE_REG 0x028
+#define BSPI_BITS_PER_CYCLE_REG 0x02C
+#define BSPI_BITS_PER_PHASE_REG 0x030
+#define BSPI_CMD_AND_MODE_BYTE_REG 0x034
+#define BSPI_FLASH_UPPER_ADDR_BYTE_REG 0x038
+#define BSPI_XOR_VALUE_REG 0x03C
+#define BSPI_XOR_ENABLE_REG 0x040
+#define BSPI_PIO_MODE_ENABLE_REG 0x044
+#define BSPI_PIO_IODIR_REG 0x048
+#define BSPI_PIO_DATA_REG 0x04C
+
+/* RAF registers */
+#define BSPI_RAF_START_ADDRESS_REG 0x00
+#define BSPI_RAF_NUM_WORDS_REG 0x04
+#define BSPI_RAF_CTRL_REG 0x08
+#define BSPI_RAF_FULLNESS_REG 0x0C
+#define BSPI_RAF_WATERMARK_REG 0x10
+#define BSPI_RAF_STATUS_REG 0x14
+#define BSPI_RAF_READ_DATA_REG 0x18
+#define BSPI_RAF_WORD_CNT_REG 0x1C
+#define BSPI_RAF_CURR_ADDR_REG 0x20
+
+#define XFER_DUAL BIT(30)
+#define XFER_QUAD BIT(31)
+
+#define FLUSH_BIT BIT(0)
+#define MAST_N_BOOT_BIT BIT(0)
+#define WRITE_LOCK_BIT BIT(0)
+
+#define CEIL(m, n) (((m) + (n) - 1) / (n))
+#define UPPER_BYTE_MASK 0xFF000000
+#define SIZE_16MB 0x001000000
+
+/*
+ * struct bcmspi_priv - qspi private structure
+ *
+ * @bspi_addr: bspi read address
+ * @bspi_4byte_addr: bspi 4 byte address mode
+ * @mspi: mspi registers block address
+ * @bspi: bspi registers block address
+ * @bspi_raf: bspi raf registers block address
+ */
+struct bcmspi_priv {
+ u32 bspi_addr;
+ bool bspi_4byte_addr;
+ fdt_addr_t mspi;
+ fdt_addr_t bspi;
+ fdt_addr_t bspi_raf;
+};
+
+/* BSPI mode */
+
+static void bspi_flush_prefetch_buffers(struct bcmspi_priv *priv)
+{
+ writel(0, priv->bspi + BSPI_B0_CTRL_REG);
+ writel(0, priv->bspi + BSPI_B1_CTRL_REG);
+ writel(FLUSH_BIT, priv->bspi + BSPI_B0_CTRL_REG);
+ writel(FLUSH_BIT, priv->bspi + BSPI_B1_CTRL_REG);
+}
+
+static int bspi_enable(struct bcmspi_priv *priv)
+{
+ /* Disable write lock */
+ writel(0, priv->mspi + MSPI_WRITE_LOCK_REG);
+ /* Flush prefetch buffers */
+ bspi_flush_prefetch_buffers(priv);
+ /* Switch to BSPI */
+ writel(0, priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG);
+
+ return 0;
+}
+
+static int bspi_disable(struct bcmspi_priv *priv)
+{
+ int ret;
+ uint val;
+
+ if ((readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG) & 1) == 0) {
+ ret = readl_poll_timeout(priv->bspi + BSPI_BUSY_STATUS_REG, val, !(val & 1),
+ BUSY_TIMEOUT_US);
+ if (ret) {
+ printf("%s: Failed to disable bspi, device busy\n", __func__);
+ return ret;
+ }
+
+ /* Switch to MSPI */
+ writel(MAST_N_BOOT_BIT, priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG);
+ udelay(BUSY_DELAY_US);
+
+ val = readl(priv->bspi + BSPI_MAST_N_BOOT_CTRL_REG);
+ if (!(val & 1)) {
+ printf("%s: Failed to enable mspi\n", __func__);
+ return -EBUSY;
+ }
+ }
+
+ /* Enable write lock */
+ writel(WRITE_LOCK_BIT, priv->mspi + MSPI_WRITE_LOCK_REG);
+
+ return 0;
+}
+
+static int bspi_read_via_raf(struct bcmspi_priv *priv, u8 *rx, uint bytes)
+{
+ u32 status;
+ uint words;
+ int aligned;
+ int ret;
+
+ /*
+ * Flush data from the previous session (unlikely)
+ * Read outstanding bits in the poll condition to empty FIFO
+ */
+ ret = readl_poll_timeout(priv->bspi_raf + BSPI_RAF_STATUS_REG,
+ status,
+ (!readl(priv->bspi_raf + BSPI_RAF_READ_DATA_REG) &&
+ status & BSPI_RAF_STATUS_FIFO_EMPTY_MASK) &&
+ !(status & BSPI_RAF_STATUS_SESSION_BUSY_MASK),
+ BUSY_TIMEOUT_US);
+ if (ret) {
+ printf("%s: Failed to flush fifo\n", __func__);
+ return ret;
+ }
+
+ /* Transfer is in words */
+ words = CEIL(bytes, 4);
+
+ /* Setup hardware */
+ if (priv->bspi_4byte_addr) {
+ u32 val = priv->bspi_addr & UPPER_BYTE_MASK;
+
+ if (val != readl(priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG)) {
+ writel(val, priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG);
+ bspi_flush_prefetch_buffers(priv);
+ }
+ }
+
+ writel(priv->bspi_addr & ~UPPER_BYTE_MASK, priv->bspi_raf + BSPI_RAF_START_ADDRESS_REG);
+ writel(words, priv->bspi_raf + BSPI_RAF_NUM_WORDS_REG);
+ writel(0, priv->bspi_raf + BSPI_RAF_WATERMARK_REG);
+
+ /* Start reading */
+ writel(BSPI_RAF_CONTROL_START_MASK, priv->bspi_raf + BSPI_RAF_CTRL_REG);
+ aligned = DWORD_ALIGNED(rx);
+ while (bytes) {
+ status = readl(priv->bspi_raf + BSPI_RAF_STATUS_REG);
+ if (!(status & BSPI_RAF_STATUS_FIFO_EMPTY_MASK)) {
+ /* RAF is LE only, convert data to host endianness */
+ u32 data = le32_to_cpu(readl(priv->bspi_raf + BSPI_RAF_READ_DATA_REG));
+
+ /* Check if we can use the whole word */
+ if (aligned && bytes >= 4) {
+ *(u32 *)rx = data;
+ rx += 4;
+ bytes -= 4;
+ } else {
+ uint chunk = min(bytes, 4U);
+
+ /* Read out bytes one by one */
+ while (chunk) {
+ *rx++ = (u8)data;
+ data >>= 8;
+ chunk--;
+ bytes--;
+ }
+ }
+
+ continue;
+ }
+ if (!(status & BSPI_RAF_STATUS_SESSION_BUSY_MASK)) {
+ /* FIFO is empty and the session is done */
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int bspi_read(struct bcmspi_priv *priv, u8 *rx, uint bytes)
+{
+ int ret;
+
+ /* Transfer data */
+ while (bytes > 0) {
+ /* Special handing since RAF cannot go across 16MB boundary */
+ uint trans = bytes;
+ /* Divide into multiple transfers if it goes across the 16MB boundary */
+ if (priv->bspi_4byte_addr && (priv->bspi_addr >> 24) !=
+ ((priv->bspi_addr + bytes) >> 24))
+ trans = SIZE_16MB - (priv->bspi_addr & ~UPPER_BYTE_MASK);
+
+ ret = bspi_read_via_raf(priv, rx, trans);
+ if (ret)
+ return ret;
+
+ priv->bspi_addr += trans;
+ rx += trans;
+ bytes -= trans;
+ }
+
+ bspi_flush_prefetch_buffers(priv);
+ return 0;
+}
+
+static void bspi_set_flex_mode(struct bcmspi_priv *priv, const struct spi_mem_op *op)
+{
+ int bpp = (op->dummy.nbytes * 8) / op->dummy.buswidth;
+ int cmd = op->cmd.opcode;
+ int bpc = ilog2(op->data.buswidth) << BSPI_BPC_DATA_SHIFT |
+ ilog2(op->addr.buswidth) << BSPI_BPC_ADDR_SHIFT |
+ ilog2(op->cmd.buswidth) << BSPI_BPC_CMD_SHIFT;
+ int so = BIT(BSPI_STRAP_OVERRIDE_SHIFT) |
+ (op->data.buswidth > 1) << BSPI_STRAP_OVERRIDE_DATA_DUAL_SHIFT |
+ (op->addr.nbytes > 3) << BSPI_STRAP_OVERRIDE_4BYTE_SHIFT |
+ (op->data.buswidth > 3) << BSPI_STRAP_OVERRIDE_DATA_QUAD_SHIFT;
+
+ /* Disable flex mode first */
+ writel(0, priv->bspi + BSPI_FLEX_MODE_ENABLE_REG);
+
+ /* Configure single, dual or quad mode */
+ writel(bpc, priv->bspi + BSPI_BITS_PER_CYCLE_REG);
+
+ /* Opcode */
+ writel(cmd, priv->bspi + BSPI_CMD_AND_MODE_BYTE_REG);
+
+ /* Count of dummy cycles */
+ writel(bpp, priv->bspi + BSPI_BITS_PER_PHASE_REG);
+
+ /* Enable 4-byte address */
+ if (priv->bspi_4byte_addr) {
+ setbits_le32(priv->bspi + BSPI_BITS_PER_PHASE_REG, BIT(BSPI_BPP_ADDR_SHIFT));
+ } else {
+ clrbits_le32(priv->bspi + BSPI_BITS_PER_PHASE_REG, BIT(BSPI_BPP_ADDR_SHIFT));
+ writel(0, priv->bspi + BSPI_FLASH_UPPER_ADDR_BYTE_REG);
+ }
+
+ /* Enable flex mode to take effect */
+ writel(1, priv->bspi + BSPI_FLEX_MODE_ENABLE_REG);
+
+ /* Flush prefetch buffers since 32MB window BSPI could be used */
+ bspi_flush_prefetch_buffers(priv);
+
+ /* Override the strap settings */
+ writel(so, priv->bspi + BSPI_STRAP_OVERRIDE_CTRL_REG);
+}
+
+static int bspi_exec_op(struct spi_slave *slave, const struct spi_mem_op *op)
+{
+ struct udevice *bus = dev_get_parent(slave->dev);
+ struct bcmspi_priv *priv = dev_get_priv(bus);
+ int ret = -ENOTSUPP;
+
+ /* BSPI read */
+ if (op->data.dir == SPI_MEM_DATA_IN &&
+ op->data.nbytes && op->addr.nbytes) {
+ priv->bspi_4byte_addr = (op->addr.nbytes > 3);
+ priv->bspi_addr = op->addr.val;
+ bspi_set_flex_mode(priv, op);
+ ret = bspi_read(priv, op->data.buf.in, op->data.nbytes);
+ }
+
+ return ret;
+}
+
+static const struct spi_controller_mem_ops bspi_mem_ops = {
+ .exec_op = bspi_exec_op,
+};
+
+/* MSPI mode */
+
+static int mspi_exec(struct bcmspi_priv *priv, uint bytes, const u8 *tx, u8 *rx, ulong flags)
+{
+ u32 cdr = CDRAM_PCS0 | CDRAM_CONT;
+ bool use_16bits = !(bytes & 1);
+
+ if (flags & XFER_QUAD) {
+ cdr |= CDRAM_QUAD_MODE;
+
+ if (!tx)
+ cdr |= CDRAM_RBIT_INPUT;
+ }
+
+ while (bytes) {
+ uint chunk;
+ uint queues;
+ uint i;
+ uint val;
+ int ret;
+
+ if (use_16bits) {
+ chunk = min(bytes, NUM_CDRAM * 2);
+ queues = (chunk + 1) / 2;
+ bytes -= chunk;
+
+ /* Fill CDRAMs */
+ for (i = 0; i < queues; i++)
+ writel(cdr | CDRAM_BITS_EN, priv->mspi + MSPI_CDRAM_REG + 4 * i);
+
+ /* Fill TXRAMs */
+ for (i = 0; i < chunk; i++)
+ writel(tx ? tx[i] : 0xff, priv->mspi + MSPI_TX_REG + 4 * i);
+ } else {
+ /* Determine how many bytes to process this time */
+ chunk = min(bytes, NUM_CDRAM);
+ queues = chunk;
+ bytes -= chunk;
+
+ /* Fill CDRAMs and TXRAMS */
+ for (i = 0; i < chunk; i++) {
+ writel(cdr, priv->mspi + MSPI_CDRAM_REG + 4 * i);
+ writel(tx ? tx[i] : 0xff, priv->mspi + MSPI_TX_REG + 8 * i);
+ }
+ }
+
+ /* Setup queue pointers */
+ writel(0, priv->mspi + MSPI_NEWQP_REG);
+ writel(queues - 1, priv->mspi + MSPI_ENDQP_REG);
+
+ /* Deassert CS if requested and it's the last transfer */
+ if (bytes == 0 && (flags & SPI_XFER_END))
+ clrbits_le32(priv->mspi + MSPI_CDRAM_REG + ((queues - 1) << 2), CDRAM_CONT);
+
+ /* Kick off */
+ writel(0, priv->mspi + MSPI_STATUS_REG);
+ if (bytes == 0 && (flags & SPI_XFER_END))
+ writel(MSPI_SPE, priv->mspi + MSPI_SPCR2_REG);
+ else
+ writel(MSPI_SPE | MSPI_CONT_AFTER_CMD,
+ priv->mspi + MSPI_SPCR2_REG);
+
+ ret = readl_poll_timeout(priv->mspi + MSPI_STATUS_REG, val, (val & 1),
+ BUSY_TIMEOUT_US);
+ if (ret) {
+ printf("%s: Failed to disable bspi, device busy\n", __func__);
+ return ret;
+ }
+
+ /* Read data out */
+ if (rx) {
+ if (use_16bits) {
+ for (i = 0; i < chunk; i++)
+ rx[i] = readl(priv->mspi + MSPI_RX_REG + 4 * i) & 0xff;
+ } else {
+ for (i = 0; i < chunk; i++)
+ rx[i] = readl(priv->mspi + MSPI_RX_REG + 8 * i + 4) & 0xff;
+ }
+ }
+
+ /* Advance pointers */
+ if (tx)
+ tx += chunk;
+ if (rx)
+ rx += chunk;
+ }
+
+ return 0;
+}
+
+static int mspi_xfer(struct udevice *dev, uint bitlen, const void *dout, void *din, ulong flags)
+{
+ struct udevice *bus = dev_get_parent(dev);
+ struct bcmspi_priv *priv = dev_get_priv(bus);
+ uint bytes;
+ int ret = 0;
+
+ /* we can only transfer multiples of 8 bits */
+ if (bitlen % 8)
+ return -EPROTONOSUPPORT;
+
+ bytes = bitlen / 8;
+
+ if (flags & SPI_XFER_BEGIN) {
+ /* Switch to MSPI */
+ ret = bspi_disable(priv);
+ if (ret)
+ return ret;
+ }
+
+ /* MSPI: Transfer */
+ if (bytes)
+ ret = mspi_exec(priv, bytes, dout, din, flags);
+
+ if (flags & SPI_XFER_END) {
+ /* Switch back to BSPI */
+ ret = bspi_enable(priv);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+/* iProc interface */
+
+static int iproc_qspi_set_speed(struct udevice *bus, uint speed)
+{
+ struct bcmspi_priv *priv = dev_get_priv(bus);
+ uint spbr;
+
+ /* MSPI: SCK configuration */
+ spbr = (QSPI_AXI_CLK - 1) / (2 * speed) + 1;
+ writel(max(min(spbr, SPBR_MAX), SPBR_MIN), priv->mspi + MSPI_SPCR0_LSB_REG);
+
+ return 0;
+}
+
+static int iproc_qspi_set_mode(struct udevice *bus, uint mode)
+{
+ struct bcmspi_priv *priv = dev_get_priv(bus);
+
+ /* MSPI: set master bit and mode */
+ writel(MSPI_MSTR /* Master */ | (mode & 3), priv->mspi + MSPI_SPCR0_MSB_REG);
+
+ return 0;
+}
+
+static int iproc_qspi_claim_bus(struct udevice *dev)
+{
+ /* Nothing to do */
+ return 0;
+}
+
+static int iproc_qspi_release_bus(struct udevice *dev)
+{
+ struct udevice *bus = dev_get_parent(dev);
+ struct bcmspi_priv *priv = dev_get_priv(bus);
+
+ /* Make sure no operation is in progress */
+ writel(0, priv->mspi + MSPI_SPCR2_REG);
+ udelay(BUSY_DELAY_US);
+
+ return 0;
+}
+
+static int iproc_qspi_of_to_plat(struct udevice *bus)
+{
+ struct bcmspi_priv *priv = dev_get_priv(bus);
+
+ priv->bspi = dev_read_addr_name(bus, "bspi");
+ if (IS_ERR((void *)priv->bspi)) {
+ printf("%s: Failed to get bspi base address\n", __func__);
+ return PTR_ERR((void *)priv->bspi);
+ }
+
+ priv->bspi_raf = dev_read_addr_name(bus, "bspi_raf");
+ if (IS_ERR((void *)priv->bspi_raf)) {
+ printf("%s: Failed to get bspi_raf base address\n", __func__);
+ return PTR_ERR((void *)priv->bspi_raf);
+ }
+
+ priv->mspi = dev_read_addr_name(bus, "mspi");
+ if (IS_ERR((void *)priv->mspi)) {
+ printf("%s: Failed to get mspi base address\n", __func__);
+ return PTR_ERR((void *)priv->mspi);
+ }
+
+ return 0;
+}
+
+static int iproc_qspi_probe(struct udevice *bus)
+{
+ struct bcmspi_priv *priv = dev_get_priv(bus);
+
+ /* configure mspi */
+ writel(0, priv->mspi + MSPI_SPCR1_LSB_REG);
+ writel(0, priv->mspi + MSPI_SPCR1_MSB_REG);
+ writel(0, priv->mspi + MSPI_NEWQP_REG);
+ writel(0, priv->mspi + MSPI_ENDQP_REG);
+ writel(0, priv->mspi + MSPI_SPCR2_REG);
+
+ /* configure bspi */
+ bspi_enable(priv);
+
+ return 0;
+}
+
+static const struct dm_spi_ops iproc_qspi_ops = {
+ .claim_bus = iproc_qspi_claim_bus,
+ .release_bus = iproc_qspi_release_bus,
+ .xfer = mspi_xfer,
+ .set_speed = iproc_qspi_set_speed,
+ .set_mode = iproc_qspi_set_mode,
+ .mem_ops = &bspi_mem_ops,
+};
+
+static const struct udevice_id iproc_qspi_ids[] = {
+ { .compatible = "brcm,iproc-qspi" },
+ { }
+};
+
+U_BOOT_DRIVER(iproc_qspi) = {
+ .name = "iproc_qspi",
+ .id = UCLASS_SPI,
+ .of_match = iproc_qspi_ids,
+ .ops = &iproc_qspi_ops,
+ .of_to_plat = iproc_qspi_of_to_plat,
+ .priv_auto = sizeof(struct bcmspi_priv),
+ .probe = iproc_qspi_probe,
+};
diff --git a/env/Kconfig b/env/Kconfig
index 6dc8d8d..b9d0472 100644
--- a/env/Kconfig
+++ b/env/Kconfig
@@ -320,6 +320,7 @@
default y if NORTHBRIDGE_INTEL_IVYBRIDGE
default y if INTEL_QUARK
default y if INTEL_QUEENSBAY
+ default y if ARCH_SUNXI
help
Define this if you have a SPI Flash memory device which you
want to use for the environment.
@@ -536,7 +537,7 @@
ENV_IS_IN_SPI_FLASH
default 0x3f8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC
default 0x140000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH
- default 0x88000 if ARCH_SUNXI
+ default 0xF0000 if ARCH_SUNXI
default 0xE0000 if ARCH_ZYNQ
default 0x1E00000 if ARCH_ZYNQMP
default 0x7F40000 if ARCH_VERSAL
@@ -559,7 +560,8 @@
config ENV_SIZE
hex "Environment Size"
default 0x40000 if ENV_IS_IN_SPI_FLASH && ARCH_ZYNQMP
- default 0x20000 if ARCH_SUNXI || ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
+ default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
+ default 0x10000 if ARCH_SUNXI
default 0x8000 if ARCH_ROCKCHIP && ENV_IS_IN_MMC
default 0x2000 if ARCH_ROCKCHIP && ENV_IS_IN_SPI_FLASH
default 0x8000 if ARCH_ZYNQMP || ARCH_VERSAL
@@ -575,6 +577,7 @@
default 0x40000 if ARCH_ZYNQMP || ARCH_VERSAL
default 0x20000 if ARCH_ZYNQ || ARCH_OMAP2PLUS || ARCH_AT91
default 0x20000 if MICROBLAZE && ENV_IS_IN_SPI_FLASH
+ default 0x10000 if ARCH_SUNXI && ENV_IS_IN_SPI_FLASH
help
Size of the sector containing the environment.
diff --git a/include/efi_loader.h b/include/efi_loader.h
index e390d32..110d8ae 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -342,7 +342,7 @@
*/
struct efi_handler {
struct list_head link;
- const efi_guid_t *guid;
+ const efi_guid_t guid;
void *protocol_interface;
struct list_head open_infos;
};
diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c
index 82128ac..d0f3e05 100644
--- a/lib/efi_loader/efi_boottime.c
+++ b/lib/efi_loader/efi_boottime.c
@@ -552,7 +552,7 @@
struct efi_handler *protocol;
protocol = list_entry(lhandle, struct efi_handler, link);
- if (!guidcmp(protocol->guid, protocol_guid)) {
+ if (!guidcmp(&protocol->guid, protocol_guid)) {
if (handler)
*handler = protocol;
return EFI_SUCCESS;
@@ -604,7 +604,7 @@
list_for_each_entry_safe(protocol, pos, &efiobj->protocols, link) {
efi_status_t ret;
- ret = efi_remove_protocol(handle, protocol->guid,
+ ret = efi_remove_protocol(handle, &protocol->guid,
protocol->protocol_interface);
if (ret != EFI_SUCCESS)
return ret;
@@ -1131,7 +1131,7 @@
handler = calloc(1, sizeof(struct efi_handler));
if (!handler)
return EFI_OUT_OF_RESOURCES;
- handler->guid = protocol;
+ memcpy((void *)&handler->guid, protocol, sizeof(efi_guid_t));
handler->protocol_interface = protocol_interface;
INIT_LIST_HEAD(&handler->open_infos);
list_add_tail(&handler->link, &efiobj->protocols);
@@ -1227,7 +1227,7 @@
/* Count all driver associations */
list_for_each_entry(handler, &handle->protocols, link) {
- if (protocol && guidcmp(handler->guid, protocol))
+ if (protocol && guidcmp(&handler->guid, protocol))
continue;
list_for_each_entry(item, &handler->open_infos, link) {
if (item->info.attributes &
@@ -1249,7 +1249,7 @@
return EFI_OUT_OF_RESOURCES;
/* Collect unique driver handles */
list_for_each_entry(handler, &handle->protocols, link) {
- if (protocol && guidcmp(handler->guid, protocol))
+ if (protocol && guidcmp(&handler->guid, protocol))
continue;
list_for_each_entry(item, &handler->open_infos, link) {
if (item->info.attributes &
@@ -2446,7 +2446,7 @@
protocol = list_entry(protocol_handle,
struct efi_handler, link);
- (*protocol_buffer)[j] = (void *)protocol->guid;
+ (*protocol_buffer)[j] = (void *)&protocol->guid;
++j;
}
}
@@ -3094,7 +3094,7 @@
(efi_handle_t)image_obj)
continue;
r = EFI_CALL(efi_close_protocol
- (efiobj, protocol->guid,
+ (efiobj, &protocol->guid,
info->info.agent_handle,
info->info.controller_handle
));
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 5df3593..9611398 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -91,7 +91,7 @@
list_for_each_entry(efiobj, &efi_obj_list, link) {
list_for_each_entry(handler, &efiobj->protocols, link) {
- if (!guidcmp(handler->guid, &efi_guid_loaded_image)) {
+ if (!guidcmp(&handler->guid, &efi_guid_loaded_image)) {
efi_print_image_info(
(struct efi_loaded_image_obj *)efiobj,
handler->protocol_interface, pc);
diff --git a/tools/kwboot.c b/tools/kwboot.c
index 69d1be0..9f2dd2d 100644
--- a/tools/kwboot.c
+++ b/tools/kwboot.c
@@ -2073,7 +2073,8 @@
bootmsg = 1;
if (prev_optind == optind)
goto usage;
- if (optind < argc - 1 && argv[optind] && argv[optind][0] != '-')
+ /* Option -b could have optional argument which specify image path */
+ if (optind < argc && argv[optind] && argv[optind][0] != '-')
imgpath = argv[optind++];
break;
@@ -2128,17 +2129,44 @@
if (!bootmsg && !term && !debugmsg && !imgpath)
goto usage;
- ttypath = argv[optind++];
+ /*
+ * If there is no remaining argument but optional imgpath was parsed
+ * then it means that optional imgpath was eaten by getopt parser.
+ * Reassing imgpath to required ttypath argument.
+ */
+ if (optind == argc && imgpath) {
+ ttypath = imgpath;
+ imgpath = NULL;
+ } else if (optind + 1 == argc) {
+ ttypath = argv[optind];
+ } else {
+ goto usage;
+ }
- if (optind != argc)
+ /* boot and debug message use baudrate 115200 */
+ if (((bootmsg && !imgpath) || debugmsg) && baudrate != 115200) {
+ fprintf(stderr, "Baudrate other than 115200 cannot be used for this operation.\n");
goto usage;
+ }
- tty = kwboot_open_tty(ttypath, imgpath ? 115200 : baudrate);
+ tty = kwboot_open_tty(ttypath, baudrate);
if (tty < 0) {
perror(ttypath);
goto out;
}
+ /*
+ * initial baudrate for image transfer is always 115200,
+ * the change to different baudrate is done only after the header is sent
+ */
+ if (imgpath && baudrate != 115200) {
+ rc = kwboot_tty_change_baudrate(tty, 115200);
+ if (rc) {
+ perror(ttypath);
+ goto out;
+ }
+ }
+
if (baudrate == 115200)
/* do not change baudrate during Xmodem to the same value */
baudrate = 0;