From ff4288265eb9b93d0014ecd54ed2351793ab1598 Mon Sep 17 00:00:00 2001 From: Piotr Dymacz Date: Wed, 2 Dec 2015 17:23:15 +0100 Subject: [PATCH] Refactor FLASH related code 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 | 217 ++++++++++++++++++++++++----------------- u-boot/include/flash.h | 151 +++++++++++++++++++--------- 2 files changed, 234 insertions(+), 134 deletions(-) diff --git a/u-boot/common/flash.c b/u-boot/common/flash.c index aa51071..1477a50 100644 --- a/u-boot/common/flash.c +++ b/u-boot/common/flash.c @@ -1,56 +1,105 @@ /* - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Copyright (C) 2015 Piotr Dymacz + * Copyright (C) 2005 Wolfgang Denk, DENX Software Engineering, * - * 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 #include -#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 */ diff --git a/u-boot/include/flash.h b/u-boot/include/flash.h index 7fab7f7..ac9ed36 100644 --- a/u-boot/include/flash.h +++ b/u-boot/include/flash.h @@ -1,46 +1,68 @@ /* - * (C) Copyright 2000-2005 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Copyright (C) 2015 Piotr Dymacz + * Copyright (C) 2005 Wolfgang Denk, DENX Software Engineering, * - * 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 */ -- 2.25.1