diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 34f68881ed..51e28bf07b 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -113,6 +113,27 @@ static int write_cr(struct spi_flash *flash, u8 wc) #endif #ifdef CONFIG_SPI_FLASH_BAR +/* + * This "clean_bar" is necessary in a situation when one was accessing + * spi flash memory > 16 MiB by using Bank Address Register's BA24 bit. + * + * After it the BA24 bit shall be cleared to allow access to correct + * memory region after SW reset (by calling "reset" command). + * + * Otherwise, the BA24 bit may be left set and then after reset, the + * ROM would read/write/erase SPL from 16 MiB * bank_sel address. + */ +static int clean_bar(struct spi_flash *flash) +{ + u8 cmd, bank_sel = 0; + + if (flash->bank_curr == 0) + return 0; + cmd = flash->bank_write_cmd; + + return spi_flash_write_common(flash, &cmd, 1, &bank_sel, 1); +} + static int write_bar(struct spi_flash *flash, u32 offset) { u8 cmd, bank_sel; @@ -339,6 +360,10 @@ int spi_flash_cmd_erase_ops(struct spi_flash *flash, u32 offset, size_t len) len -= erase_size; } +#ifdef CONFIG_SPI_FLASH_BAR + ret = clean_bar(flash); +#endif + return ret; } @@ -397,6 +422,10 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, offset += chunk_len; } +#ifdef CONFIG_SPI_FLASH_BAR + ret = clean_bar(flash); +#endif + return ret; } @@ -500,6 +529,10 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, data += read_len; } +#ifdef CONFIG_SPI_FLASH_BAR + ret = clean_bar(flash); +#endif + free(cmd); return ret; } diff --git a/drivers/mtd/spi/sunxi_spi_spl.c b/drivers/mtd/spi/sunxi_spi_spl.c index 852abd41de..35835c2798 100644 --- a/drivers/mtd/spi/sunxi_spi_spl.c +++ b/drivers/mtd/spi/sunxi_spi_spl.c @@ -8,6 +8,7 @@ #include #include #include +#include #ifdef CONFIG_SPL_OS_BOOT #error CONFIG_SPL_OS_BOOT is not supported yet @@ -261,27 +262,51 @@ static void spi0_read_data(void *buf, u32 addr, u32 len) } } +static ulong spi_load_read(struct spl_load_info *load, ulong sector, + ulong count, void *buf) +{ + spi0_read_data(buf, sector, count); + + return count; +} + /*****************************************************************************/ static int spl_spi_load_image(struct spl_image_info *spl_image, struct spl_boot_device *bootdev) { - int err; + int ret = 0; struct image_header *header; header = (struct image_header *)(CONFIG_SYS_TEXT_BASE); spi0_init(); spi0_read_data((void *)header, CONFIG_SYS_SPI_U_BOOT_OFFS, 0x40); - err = spl_parse_image_header(spl_image, header); - if (err) - return err; - spi0_read_data((void *)spl_image->load_addr, CONFIG_SYS_SPI_U_BOOT_OFFS, - spl_image->size); + if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) && + image_get_magic(header) == FDT_MAGIC) { + struct spl_load_info load; + + debug("Found FIT image\n"); + load.dev = NULL; + load.priv = NULL; + load.filename = NULL; + load.bl_len = 1; + load.read = spi_load_read; + ret = spl_load_simple_fit(spl_image, &load, + CONFIG_SYS_SPI_U_BOOT_OFFS, header); + } else { + ret = spl_parse_image_header(spl_image, header); + if (ret) + return ret; + + spi0_read_data((void *)spl_image->load_addr, + CONFIG_SYS_SPI_U_BOOT_OFFS, spl_image->size); + } spi0_deinit(); - return 0; + + return ret; } /* Use priorty 0 to override the default if it happens to be linked in */ SPL_LOAD_IMAGE_METHOD("sunxi SPI", 0, BOOT_DEVICE_SPI, spl_spi_load_image);