From ba09440131a707c4fabf2875b14521bcf2b86938 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 22 Sep 2017 22:57:22 +0100 Subject: SPL: SPI: sunxi: add SPL FIT image support The sunxi-specific SPI load routine only knows how to load a legacy U-Boot image. Teach it how to handle FIT images as well, simply by providing the existing SPL FIT loader with the right loader routine to access the SPI NOR flash. Signed-off-by: Andre Przywara Reported-by: Peter Kosa Acked-by: Maxime Ripard Reviewed-by: Jagan Teki --- drivers/mtd/spi/sunxi_spi_spl.c | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'drivers') 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); -- cgit v1.2.3 From ca1ac16da097bf0ab176b1a201653553160dc042 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Mon, 25 Sep 2017 12:40:08 +0200 Subject: sf: bar: Clean BA24 Bank Address Register bit after read/write/erase operation The content of Bank Address Register (BAR) is volatile. It is cleared after power cycle or reset command (RESET F0h). Some memories (like e.g. s25fl256s) use it to access memory larger than 0x1000000 (16 MiB). The problem shows up when one: 1. Reads/writes/erases memory > 16 MiB 2. Calls "reset" u-boot command (which is not causing BAR to be cleared) In the above scenario, the SoC ROM sends 0x000000 address to read SPL. Unfortunately, the BA24 bit is still set and hence it receives content from 0x1000000 (16 MiB) memory address. As a result the SoC aborts and we hang. Only power cycle can take the SoC out of this state. How to reproduce/test: sf probe; sf erase 0x1200000 0x800000; reset sf probe; sf erase 0x1200000 0x800000; sf write 0x11000000 0x1200000 0x800000; reset sf probe; sf read 0x11000000 0x1200000 0x800000; reset Signed-off-by: Lukasz Majewski [Fixed comment text on clean_bar function] Signed-off-by: Jagan Teki Reviewed-by: Jagan Teki --- drivers/mtd/spi/spi_flash.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'drivers') 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; } -- cgit v1.2.3