/*
- * (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.
* 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 */
/*
- * (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 */
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 */