Refactor FLASH related code
authorPiotr Dymacz <pepe2k@gmail.com>
Wed, 2 Dec 2015 16:23:15 +0000 (17:23 +0100)
committerPiotr Dymacz <pepe2k@gmail.com>
Wed, 2 Dec 2015 16:23:15 +0000 (17:23 +0100)
Add more information fields in FLASH description structure, add list of supported chips,
move some defines related with SPI NOR FLASH to flash.h, clean and reformat code.

u-boot/common/flash.c
u-boot/include/flash.h

index aa51071543daddd2b97ef1bbfae3e52aff2daf9c..1477a50c2b3ed25d27446ec920e92a2d735f1cfe 100644 (file)
 /*
- * (C) Copyright 2000
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Copyright (C) 2015 Piotr Dymacz <piotr@dymacz.pl>
+ * Copyright (C) 2005 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:GPL-2.0
  */
 
-/* #define DEBUG */
-
 #include <common.h>
 #include <flash.h>
 
-#if !defined(CFG_NO_FLASH)
+#ifndef CFG_NO_FLASH
 
-extern flash_info_t flash_info[]; /* info for FLASH chips */
+/* Info for FLASH chips */
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
 
-/*-----------------------------------------------------------------------
- * Functions
- */
-flash_info_t * addr2info(ulong addr){
+/* List of supported and known SPI NOR FLASH chips */
+static char VENDOR_ATMEL[]    = "Atmel";
+static char VENDOR_EON[]      = "EON";
+static char VENDOR_MACRONIX[] = "Macronix";
+static char VENDOR_MICRON[]   = "Micron";
+static char VENDOR_SPANSION[] = "Spansion";
+static char VENDOR_WINBOND[]  = "Winbond";
+
+const spi_nor_ids_info_t spi_nor_ids[] = {
+       /* 4 MiB */
+       { "AT25DF321", 0x1F4700, SIZE_4MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "EN25Q32",   0x1C3016, SIZE_4MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "EN25F32",   0x1C3116, SIZE_4MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "MX25L320",  0xC22016, SIZE_4MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "M25P32",    0x202016, SIZE_4MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "S25FL032P", 0x010215, SIZE_4MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "W25Q32",    0xEF4016, SIZE_4MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+
+       /* 8 MiB */
+       { "AT25DF641", 0x1F4800, SIZE_8MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "EN25Q64",   0x1C3017, SIZE_8MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "MX25L64",   0xC22017, SIZE_8MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "MX25L64",   0xC22617, SIZE_8MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "M25P64",    0x202017, SIZE_8MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "S25FL064P", 0x010216, SIZE_8MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "W25Q64",    0xEF4017, SIZE_8MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+
+       /* 16 MiB */
+       { "MX25L128",  0xC22018, SIZE_16MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "MX25L128",  0xC22618, SIZE_16MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "N25Q128",   0x20BA18, SIZE_16MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "S25FL127S", 0x012018, SIZE_16MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+       { "W25Q128",   0xEF4018, SIZE_16MiB, SIZE_64KiB, 256, SPI_FLASH_CMD_ES_64KB },
+};
+
+const u32 spi_nor_ids_count = sizeof(spi_nor_ids) / sizeof(spi_nor_ids_info_t);
+
+const char *flash_manuf_name(u32 jedec_id)
+{
+       switch (jedec_id >> 16) {
+       case FLASH_VENDOR_JEDEC_ATMEL:
+               return VENDOR_ATMEL;
+               break;
+       case FLASH_VENDOR_JEDEC_EON:
+               return VENDOR_EON;
+               break;
+       case FLASH_VENDOR_JEDEC_MACRONIX:
+               return VENDOR_MACRONIX;
+               break;
+       case FLASH_VENDOR_JEDEC_MICRON:
+               return VENDOR_MICRON;
+               break;
+       case FLASH_VENDOR_JEDEC_SPANSION:
+               return VENDOR_SPANSION;
+               break;
+       case FLASH_VENDOR_JEDEC_WINBOND:
+               return VENDOR_WINBOND;
+               break;
+       default:
+               return "Unknown";
+               break;
+       }
+}
+
+flash_info_t *addr2info(ulong addr)
+{
        flash_info_t *info;
        int i;
 
-       for(i = 0, info = &flash_info[0]; i < CFG_MAX_FLASH_BANKS; ++i, ++info){
-               /* WARNING - The '- 1' is needed if the flash
+       for (i = 0, info = &flash_info[0]; i < CFG_MAX_FLASH_BANKS; ++i, ++info) {
+               /*
+                * WARNING - The '- 1' is needed if the flash
                 * is at the end of the address space, since
                 * info->start[0] + info->size wraps back to 0.
                 * Please don't change this unless you understand this.
                 */
-               if(info->flash_id != FLASH_UNKNOWN && addr >= info->start[0] && addr <= info->start[0] + info->size - 1){
-                       return(info);
+               if (info->flash_id != FLASH_UNKNOWN
+                       && addr >= info->start[0]
+                       && addr <= info->start[0] + info->size - 1) {
+                       return info;
                }
        }
-       return(NULL);
+
+       return NULL;
 }
 
-/*-----------------------------------------------------------------------
+/*
  * Copy memory to flash.
  * Make sure all target addresses are within Flash bounds,
  * and no protected sectors are hit.
@@ -61,75 +110,69 @@ flash_info_t * addr2info(ulong addr){
  * ERR_PROTECTED   4 - target range includes protected sectors
  * ERR_INVAL       8 - target address not in Flash memory
  * ERR_ALIGN       16 - target address not aligned on boundary
- *                     (only some targets require alignment)
+ *                      (only some targets require alignment)
  */
-int flash_write(char *src, ulong addr, ulong cnt){
+int flash_write(char *src, ulong addr, ulong cnt)
+{
        int i;
        ulong end = addr + cnt - 1;
        flash_info_t *info_first = addr2info(addr);
        flash_info_t *info_last = addr2info(end);
        flash_info_t *info;
 
-       if(cnt == 0){
-               return(ERR_OK);
-       }
+       if (cnt == 0)
+               return ERR_OK;
 
-       if(!info_first || !info_last){
-               return(ERR_INVAL);
-       }
+       if (!info_first || !info_last)
+               return ERR_INVAL;
 
-       /* finally write data to flash */
-       for(info = info_first; info <= info_last && cnt > 0; ++info){
-               ulong len;
+       /* Finally write data to flash */
+       for (info = info_first; info <= info_last && cnt > 0; ++info) {
+               ulong len = info->start[0] + info->size - addr;
 
-               len = info->start[0] + info->size - addr;
-               if(len > cnt){
+               if (len > cnt)
                        len = cnt;
-               }
-               if((i = write_buff(info, (uchar *)src, addr, len)) != 0){
-                       return(i);
-               }
-               cnt -= len;
+
+               if ((i = write_buff(info, (uchar *)src, addr, len)) != 0)
+                       return i;
+
+               cnt  -= len;
                addr += len;
-               src += len;
+               src  += len;
        }
-       return(ERR_OK);
-}
 
-/*-----------------------------------------------------------------------
- */
+       return ERR_OK;
+}
 
-void flash_perror(int err){
-       switch(err){
-               case ERR_OK:
-                       break;
-               case ERR_TIMOUT:
-                       puts("## Error: timeout writing to FLASH\n");
-                       break;
-               case ERR_NOT_ERASED:
-                       puts("## Error: FLASH not erased\n");
-                       break;
-               case ERR_INVAL:
-                       puts("## Error: outside available FLASH\n");
-                       break;
-               case ERR_ALIGN:
-                       puts("## Error: start and/or end address not on sector boundary\n");
-                       break;
-               case ERR_UNKNOWN_FLASH_VENDOR:
-                       puts("## Error: unknown vendor of FLASH\n");
-                       break;
-               case ERR_UNKNOWN_FLASH_TYPE:
-                       puts("## Error: unknown type of FLASH\n");
-                       break;
-               case ERR_PROG_ERROR:
-                       puts("## Error: general FLASH programming error\n");
-                       break;
-               default:
-                       printf("## Error: %s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
-                       break;
+void flash_perror(int err)
+{
+       switch (err) {
+       case ERR_OK:
+               break;
+       case ERR_TIMOUT:
+               puts("## Error: timeout writing to FLASH\n");
+               break;
+       case ERR_NOT_ERASED:
+               puts("## Error: FLASH not erased\n");
+               break;
+       case ERR_INVAL:
+               puts("## Error: outside available FLASH\n");
+               break;
+       case ERR_ALIGN:
+               puts("## Error: start and/or end address not on sector boundary\n");
+               break;
+       case ERR_UNKNOWN_FLASH_VENDOR:
+               puts("## Error: unknown vendor of FLASH\n");
+               break;
+       case ERR_UNKNOWN_FLASH_TYPE:
+               puts("## Error: unknown type of FLASH\n");
+               break;
+       case ERR_PROG_ERROR:
+               puts("## Error: general FLASH programming error\n");
+               break;
+       default:
+               printf("## Error: %s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err);
+               break;
        }
 }
-
-/*-----------------------------------------------------------------------
- */
 #endif /* !CFG_NO_FLASH */
index 7fab7f7bf9b6a40ec6597e9eca56eb3a96b0f9d4..ac9ed36d97dc74b9b1fe293e4784aecf22ff7145 100644 (file)
@@ -1,46 +1,68 @@
 /*
- * (C) Copyright 2000-2005
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ * Copyright (C) 2015 Piotr Dymacz <piotr@dymacz.pl>
+ * Copyright (C) 2005 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.         See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:GPL-2.0
  */
 
 #ifndef _FLASH_H_
 #define _FLASH_H_
 
 #ifndef CFG_NO_FLASH
-/*-----------------------------------------------------------------------
- * FLASH Info: contains chip specific data, per FLASH bank
- */
 
+/*
+ * Struct for info about FLASH chip/bank, with:
+ * - manufacturer and model names
+ * - JEDEC ID (combined device & manufacturer code)
+ * - total bank size in bytes
+ * - size of erase unit in bytes
+ * - bank number
+ * - size of program page in bytes
+ * - number of erase units
+ * - erase command
+ * - physical sector start addresses
+ */
 typedef struct {
-       ulong   size;                                                   /* total bank size in bytes             */
-       ulong   sector_size;                                    /* size of erase unit in bytes */
-       ushort  sector_count;                                   /* number of erase units                */
-       ulong   flash_id;                                               /* combined device & manufacturer code  */
-       ulong   start[CFG_MAX_FLASH_SECT];              /* physical sector start addresses */
+       char *manuf_name;
+       char *model_name;
+       u32 flash_id;
+       u32 size;
+       u32 sector_size;
+       u32 bank;
+       u16 page_size;
+       u16 sector_count;
+       u8  erase_cmd;
+       u32 start[CFG_MAX_FLASH_SECT];
 } flash_info_t;
 
+extern flash_info_t flash_info[];
+
+/*
+ * Struct for info about supported SPI NOR FLASH chips, with:
+ * - model names
+ * - JEDEC ID (combined device & manufacturer code)
+ * - total size in bytes
+ * - size of erase unit in bytes
+ * - size of program page in bytes
+ * - erase command
+ */
+typedef struct {
+       char *model_name;
+       u32 flash_id;
+       u32 size;
+       u32 sector_size;
+       u16 page_size;
+       u8  erase_cmd;
+} spi_nor_ids_info_t;
+
+extern const spi_nor_ids_info_t spi_nor_ids[];
+extern const u32 spi_nor_ids_count;
 
 /* Prototypes */
-extern unsigned long flash_init (void);
-extern int flash_erase(flash_info_t *, int, int);
+u32 flash_init(void);
+u32 flash_erase(flash_info_t *info, u32 s_first, u32 s_last);
+const char* flash_manuf_name(u32 jedec_id);
+
 extern int flash_sect_erase(ulong addr_first, ulong addr_last);
 
 /* common/flash.c */
@@ -48,24 +70,59 @@ 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);
 
-/*-----------------------------------------------------------------------
- * return codes from flash_write():
- */
-#define ERR_OK                                         0
-#define ERR_TIMOUT                                     1
-#define ERR_NOT_ERASED                         2
-#define ERR_PROTECTED                          4
-#define ERR_INVAL                                      8
-#define ERR_ALIGN                                      16
-#define ERR_UNKNOWN_FLASH_VENDOR       32
-#define ERR_UNKNOWN_FLASH_TYPE         64
-#define ERR_PROG_ERROR                         128
-
-/*-----------------------------------------------------------------------
- * Device IDs
- */
-#define FLASH_CUSTOM    0x1111
-#define FLASH_UNKNOWN  0xFFFF          /* unknown flash type */
+/* Useful size */
+#define SIZE_4KiB       4 * 1024
+#define SIZE_64KiB     64 * 1024
+
+#define SIZE_4MiB       4 * 1024 * 1024
+#define SIZE_8MiB       8 * 1024 * 1024
+#define SIZE_16MiB     16 * 1024 * 1024
+#define SIZE_32MiB     32 * 1024 * 1024
+#define SIZE_64MiB     64 * 1024 * 1024
+
+/* Return codes from flash_write(): */
+#define ERR_OK                                                 0
+#define ERR_TIMOUT                                             1
+#define ERR_NOT_ERASED                                 2
+#define ERR_PROTECTED                                  4
+#define ERR_INVAL                                              8
+#define ERR_ALIGN                                              16
+#define ERR_UNKNOWN_FLASH_VENDOR               32
+#define ERR_UNKNOWN_FLASH_TYPE                 64
+#define ERR_PROG_ERROR                                 128
+
+/* FLASH vendors IDs */
+#define FLASH_VENDOR_JEDEC_ATMEL               0x1F
+#define FLASH_VENDOR_JEDEC_EON                 0x1C
+#define FLASH_VENDOR_JEDEC_MACRONIX            0xC2
+#define FLASH_VENDOR_JEDEC_MICRON              0x20
+#define FLASH_VENDOR_JEDEC_SPANSION            0x01
+#define FLASH_VENDOR_JEDEC_WINBOND             0xEF
+
+/* Device IDs */
+#define FLASH_UNKNOWN  0xFFFFFF
+#define FLASH_CUSTOM   0x111111
+
+/* Basic SPI FLASH commands */
+#define SPI_FLASH_CMD_WRSR             0x01
+#define SPI_FLASH_CMD_PP               0x02
+#define SPI_FLASH_CMD_READ             0x03
+#define SPI_FLASH_CMD_WRDI             0x04
+#define SPI_FLASH_CMD_RDSR             0x05
+#define SPI_FLASH_CMD_WREN             0x06
+
+/* SPI FLASH erase related commands */
+#define SPI_FLASH_CMD_ES_4KB   0x20
+#define SPI_FLASH_CMD_ES_32KB  0x52
+#define SPI_FLASH_CMD_ES_64KB  0xD8
+#define SPI_FLASH_CMD_ES_ALL   0xC7
+
+/* Other SPI FLASH commands */
+#define SPI_FLASH_CMD_JEDEC            0x9F
+#define SPI_FLASH_CMD_SFDP             0x5A
+
+/* SFDP related defines */
+#define SPI_FLASH_SFDP_SIGN            0x50444653
 
 #endif /* !CFG_NO_FLASH */