Add new file with FLASH related common code for all QCA boards
authorPiotr Dymacz <pepe2k@gmail.com>
Wed, 2 Dec 2015 18:08:27 +0000 (19:08 +0100)
committerPiotr Dymacz <pepe2k@gmail.com>
Wed, 2 Dec 2015 18:08:27 +0000 (19:08 +0100)
u-boot/board/ar7240/common/spi_flash.c [new file with mode: 0644]
u-boot/include/flash.h

diff --git a/u-boot/board/ar7240/common/spi_flash.c b/u-boot/board/ar7240/common/spi_flash.c
new file mode 100644 (file)
index 0000000..d066571
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2015 Piotr Dymacz <piotr@dymacz.pl>
+ *
+ * SPDX-License-Identifier:GPL-2.0
+ */
+
+#include <config.h>
+#include <common.h>
+#include <flash.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <soc/qca_soc_common.h>
+
+/* We need it in case of unknown FLASH chip */
+#ifndef DEFAULT_FLASH_SIZE_IN_MB
+       #error "DEFAULT_FLASH_SIZE_IN_MB not defined!"
+#endif
+
+/*
+ * Find SPI NOR FLASH chip info for selected bank,
+ * based on JEDEC ID and copy data to global flash_info variable
+ */
+static u32 flash_info_find(flash_info_t *info, u32 jedec_id)
+{
+       u32 i;
+
+       for (i = 0; i < spi_nor_ids_count; i++) {
+               if (jedec_id == spi_nor_ids[i].flash_id) {
+                       info->model_name   = spi_nor_ids[i].model_name;
+                       info->size         = spi_nor_ids[i].size;
+                       info->sector_size  = spi_nor_ids[i].sector_size;
+                       info->page_size    = spi_nor_ids[i].page_size;
+                       info->erase_cmd    = spi_nor_ids[i].erase_cmd;
+                       info->sector_count = info->size / info->sector_size;
+
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+u32 flash_init(void)
+{
+       u32 bank, i, jedec_id, sfdp_size, sfdp_ss;
+       u32 total_size = 0;
+       flash_info_t *info;
+       u8 sfdp_ec;
+
+       for (bank = 0; bank < CFG_MAX_FLASH_BANKS; bank++) {
+               info = &flash_info[bank];
+
+               jedec_id = qca_sf_jedec_id(bank);
+
+               if (jedec_id == 0) {
+                       printf("## Error: SPI NOR FLASH chip in bank #%d\n"
+                                  "   is not responding, skipping\n\n", bank + 1);
+                       continue;
+               }
+
+               info->manuf_name = (char *)flash_manuf_name(jedec_id);
+               info->flash_id   = jedec_id;
+               info->bank       = bank;
+
+               if (flash_info_find(info, jedec_id) != 0) {
+                       /* Try to get some info about FLASH from SFDP */
+                       if (qca_sf_sfdp_info(bank, &sfdp_size, &sfdp_ss, &sfdp_ec) == 0) {
+                               info->size        = sfdp_size;
+                               info->sector_size = sfdp_ss;
+                               info->erase_cmd   = sfdp_ec;
+
+                               printf("** Warning: SPI NOR FLASH in bank #%d is\n"
+                                          "   unknown, JEDEC ID: 0x%06X\n\n", bank + 1, jedec_id);
+
+                               printf("   Information provided in SFDP:\n"
+                                          "   - FLASH size: ");
+                               print_size(sfdp_size, "\n");
+
+                               printf("   - erase sector size: ");
+                               print_size(sfdp_ss, "\n");
+
+                               printf("   - erase sector command: 0x%02X\n\n", sfdp_ec);
+                       } else {
+                               #if (DEFAULT_FLASH_SIZE_IN_MB == 4)
+                               info->size = SIZE_4MiB;
+                               #elif (DEFAULT_FLASH_SIZE_IN_MB == 8)
+                               info->size = SIZE_8MiB;
+                               #elif (DEFAULT_FLASH_SIZE_IN_MB == 16)
+                               info->size = SIZE_16MiB;
+                               #endif
+
+                               printf("## Error: SPI NOR FLASH chip in bank #%d\n"
+                                          "   is unknown, JEDEC ID: 0x%06X, will\n"
+                                          "   use fixed/predefined size: ", bank + 1, jedec_id);
+                               print_size(info->size, "\n\n");
+
+                               /*
+                                * Use 64 KiB erase sector/block size for unknown chip
+                                * Hopefully will work in most cases
+                                */
+                               info->sector_size = SIZE_64KiB;
+                               info->erase_cmd   = SPI_FLASH_CMD_ES_64KB;
+                               info->flash_id    = FLASH_CUSTOM;
+                       }
+
+                       /* We assume page size to be 256 bytes */
+                       info->page_size    = 256;
+                       info->model_name   = "unknown model";
+                       info->sector_count = info->size / info->sector_size;
+               }
+
+               for (i = 0; i < info->sector_count; i++){
+                       info->start[i] = CFG_FLASH_BASE
+                                                        + total_size + (i * info->sector_size);
+               }
+
+               total_size += flash_info[bank].size;
+       }
+
+       return total_size;
+}
+
+u32 flash_erase(flash_info_t *info,
+                               u32 s_first,
+                               u32 s_last)
+{
+       u32 i, j;
+
+       printf("Erasing: ");
+
+       j = 0;
+       for (i = s_first; i <= s_last; i++) {
+               qca_sf_sect_erase(info->bank, i * info->sector_size,
+                                                 info->sector_size, info->erase_cmd);
+
+               if (j == 39) {
+                       puts("\n         ");
+                       j = 0;
+               }
+               puts("#");
+
+               j++;
+       }
+
+       printf("\n\n");
+
+       return 0;
+}
+
+
+
+/*
+ * Write a buffer from memory to a FLASH:
+ * call page program for every <= 256 bytes
+ *
+ * Assumption: caller has already erased the appropriate sectors
+ */
+u32 write_buff(flash_info_t *info, uchar *source, ulong addr, ulong len)
+{
+       u32 total = 0, len_this_lp, bytes_this_page;
+       u32 dst;
+       u8 *src;
+
+       printf("Writting at address: 0x%08lX\n", addr);
+       addr = addr - CFG_FLASH_BASE;
+
+       while (total < len) {
+               src = source + total;
+               dst = addr + total;
+               bytes_this_page = info->page_size - (addr % info->page_size);
+               len_this_lp = ((len - total) > bytes_this_page) ? bytes_this_page : (len - total);
+
+               qca_sf_write_page(info->bank, dst, len_this_lp, src);
+
+               total += len_this_lp;
+       }
+
+       puts("\n");
+
+       return 0;
+}
index ac9ed36d97dc74b9b1fe293e4784aecf22ff7145..16e9810f4ed7784e7ca2da15f4a2d0a424a5e5e1 100644 (file)
@@ -61,14 +61,14 @@ extern const u32 spi_nor_ids_count;
 /* Prototypes */
 u32 flash_init(void);
 u32 flash_erase(flash_info_t *info, u32 s_first, u32 s_last);
-const charflash_manuf_name(u32 jedec_id);
+const char *flash_manuf_name(u32 jedec_id);
 
 extern int flash_sect_erase(ulong addr_first, ulong addr_last);
 
 /* common/flash.c */
 extern int flash_write(char *, ulong, ulong);
 extern flash_info_t *addr2info(ulong);
-extern int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt);
+extern u32 write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt);
 
 /* Useful size */
 #define SIZE_4KiB       4 * 1024