159829cc1SJean-Christophe PLAGNIOL-VILLARD /* 259829cc1SJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2002-2004 359829cc1SJean-Christophe PLAGNIOL-VILLARD * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com 459829cc1SJean-Christophe PLAGNIOL-VILLARD * 559829cc1SJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2003 Arabella Software Ltd. 659829cc1SJean-Christophe PLAGNIOL-VILLARD * Yuli Barcohen <yuli@arabellasw.com> 759829cc1SJean-Christophe PLAGNIOL-VILLARD * 859829cc1SJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2004 959829cc1SJean-Christophe PLAGNIOL-VILLARD * Ed Okerson 1059829cc1SJean-Christophe PLAGNIOL-VILLARD * 1159829cc1SJean-Christophe PLAGNIOL-VILLARD * Copyright (C) 2006 1259829cc1SJean-Christophe PLAGNIOL-VILLARD * Tolunay Orkun <listmember@orkun.us> 1359829cc1SJean-Christophe PLAGNIOL-VILLARD * 1459829cc1SJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 1559829cc1SJean-Christophe PLAGNIOL-VILLARD * project. 1659829cc1SJean-Christophe PLAGNIOL-VILLARD * 1759829cc1SJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 1859829cc1SJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 1959829cc1SJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 2059829cc1SJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 2159829cc1SJean-Christophe PLAGNIOL-VILLARD * 2259829cc1SJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 2359829cc1SJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 2459829cc1SJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 2559829cc1SJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 2659829cc1SJean-Christophe PLAGNIOL-VILLARD * 2759829cc1SJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 2859829cc1SJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 2959829cc1SJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 3059829cc1SJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 3159829cc1SJean-Christophe PLAGNIOL-VILLARD * 3259829cc1SJean-Christophe PLAGNIOL-VILLARD */ 3359829cc1SJean-Christophe PLAGNIOL-VILLARD 3459829cc1SJean-Christophe PLAGNIOL-VILLARD /* The DEBUG define must be before common to enable debugging */ 3559829cc1SJean-Christophe PLAGNIOL-VILLARD /* #define DEBUG */ 3659829cc1SJean-Christophe PLAGNIOL-VILLARD 3759829cc1SJean-Christophe PLAGNIOL-VILLARD #include <common.h> 3859829cc1SJean-Christophe PLAGNIOL-VILLARD #include <asm/processor.h> 3959829cc1SJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h> 4059829cc1SJean-Christophe PLAGNIOL-VILLARD #include <asm/byteorder.h> 4159829cc1SJean-Christophe PLAGNIOL-VILLARD #include <environment.h> 4259829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_CFI_DRIVER 4359829cc1SJean-Christophe PLAGNIOL-VILLARD 4459829cc1SJean-Christophe PLAGNIOL-VILLARD /* 457e5b9b47SHaavard Skinnemoen * This file implements a Common Flash Interface (CFI) driver for 467e5b9b47SHaavard Skinnemoen * U-Boot. 477e5b9b47SHaavard Skinnemoen * 487e5b9b47SHaavard Skinnemoen * The width of the port and the width of the chips are determined at 497e5b9b47SHaavard Skinnemoen * initialization. These widths are used to calculate the address for 507e5b9b47SHaavard Skinnemoen * access CFI data structures. 5159829cc1SJean-Christophe PLAGNIOL-VILLARD * 5259829cc1SJean-Christophe PLAGNIOL-VILLARD * References 5359829cc1SJean-Christophe PLAGNIOL-VILLARD * JEDEC Standard JESD68 - Common Flash Interface (CFI) 5459829cc1SJean-Christophe PLAGNIOL-VILLARD * JEDEC Standard JEP137-A Common Flash Interface (CFI) ID Codes 5559829cc1SJean-Christophe PLAGNIOL-VILLARD * Intel Application Note 646 Common Flash Interface (CFI) and Command Sets 5659829cc1SJean-Christophe PLAGNIOL-VILLARD * Intel 290667-008 3 Volt Intel StrataFlash Memory datasheet 5759829cc1SJean-Christophe PLAGNIOL-VILLARD * AMD CFI Specification, Release 2.0 December 1, 2001 5859829cc1SJean-Christophe PLAGNIOL-VILLARD * AMD/Spansion Application Note: Migration from Single-byte to Three-byte 5959829cc1SJean-Christophe PLAGNIOL-VILLARD * Device IDs, Publication Number 25538 Revision A, November 8, 2001 6059829cc1SJean-Christophe PLAGNIOL-VILLARD * 617e5b9b47SHaavard Skinnemoen * Define CFG_WRITE_SWAPPED_DATA, if you have to swap the Bytes between 6259829cc1SJean-Christophe PLAGNIOL-VILLARD * reading and writing ... (yes there is such a Hardware). 6359829cc1SJean-Christophe PLAGNIOL-VILLARD */ 6459829cc1SJean-Christophe PLAGNIOL-VILLARD 6559829cc1SJean-Christophe PLAGNIOL-VILLARD #ifndef CFG_FLASH_BANKS_LIST 6659829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE } 6759829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 6859829cc1SJean-Christophe PLAGNIOL-VILLARD 6959829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_CFI 0x98 7059829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_READ_ID 0x90 7159829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_RESET 0xff 7259829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_BLOCK_ERASE 0x20 7359829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_ERASE_CONFIRM 0xD0 7459829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_WRITE 0x40 7559829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_PROTECT 0x60 7659829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_PROTECT_SET 0x01 7759829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_PROTECT_CLEAR 0xD0 7859829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_CLEAR_STATUS 0x50 7959829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_WRITE_TO_BUFFER 0xE8 8059829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_CMD_WRITE_BUFFER_CONFIRM 0xD0 8159829cc1SJean-Christophe PLAGNIOL-VILLARD 8259829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_DONE 0x80 8359829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_ESS 0x40 8459829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_ECLBS 0x20 8559829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_PSLBS 0x10 8659829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_VPENS 0x08 8759829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_PSS 0x04 8859829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_DPS 0x02 8959829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_R 0x01 9059829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_STATUS_PROTECT 0x01 9159829cc1SJean-Christophe PLAGNIOL-VILLARD 9259829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_RESET 0xF0 9359829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_WRITE 0xA0 9459829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_ERASE_START 0x80 9559829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_ERASE_SECTOR 0x30 9659829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_UNLOCK_START 0xAA 9759829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_UNLOCK_ACK 0x55 9859829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_WRITE_TO_BUFFER 0x25 9959829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_CMD_WRITE_BUFFER_CONFIRM 0x29 10059829cc1SJean-Christophe PLAGNIOL-VILLARD 10159829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_STATUS_TOGGLE 0x40 10259829cc1SJean-Christophe PLAGNIOL-VILLARD #define AMD_STATUS_ERROR 0x20 10359829cc1SJean-Christophe PLAGNIOL-VILLARD 10459829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_MANUFACTURER_ID 0x00 10559829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_DEVICE_ID 0x01 10659829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_DEVICE_ID2 0x0E 10759829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_DEVICE_ID3 0x0F 10859829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_CFI 0x55 10959829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_CFI_ALT 0x555 11059829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_CFI_RESP 0x10 11159829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_PRIMARY_VENDOR 0x13 1127e5b9b47SHaavard Skinnemoen /* extended query table primary address */ 1137e5b9b47SHaavard Skinnemoen #define FLASH_OFFSET_EXT_QUERY_T_P_ADDR 0x15 11459829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_WTOUT 0x1F 11559829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_WBTOUT 0x20 11659829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_ETOUT 0x21 11759829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_CETOUT 0x22 11859829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_WMAX_TOUT 0x23 11959829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_WBMAX_TOUT 0x24 12059829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_EMAX_TOUT 0x25 12159829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_CEMAX_TOUT 0x26 12259829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_SIZE 0x27 12359829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_INTERFACE 0x28 12459829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_BUFFER_SIZE 0x2A 12559829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_NUM_ERASE_REGIONS 0x2C 12659829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_ERASE_REGIONS 0x2D 12759829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_PROTECT 0x02 12859829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_USER_PROTECTION 0x85 12959829cc1SJean-Christophe PLAGNIOL-VILLARD #define FLASH_OFFSET_INTEL_PROTECTION 0x81 13059829cc1SJean-Christophe PLAGNIOL-VILLARD 13159829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_NONE 0 13259829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_INTEL_EXTENDED 1 13359829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_AMD_STANDARD 2 13459829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_INTEL_STANDARD 3 13559829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_AMD_EXTENDED 4 13659829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_MITSU_STANDARD 256 13759829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_MITSU_EXTENDED 257 13859829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFI_CMDSET_SST 258 13959829cc1SJean-Christophe PLAGNIOL-VILLARD 14059829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_CFI_AMD_RESET /* needed for STM_ID_29W320DB on UC100 */ 14159829cc1SJean-Christophe PLAGNIOL-VILLARD # undef FLASH_CMD_RESET 14259829cc1SJean-Christophe PLAGNIOL-VILLARD # define FLASH_CMD_RESET AMD_CMD_RESET /* use AMD-Reset instead */ 14359829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 14459829cc1SJean-Christophe PLAGNIOL-VILLARD 14559829cc1SJean-Christophe PLAGNIOL-VILLARD typedef union { 14659829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned char c; 14759829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned short w; 14859829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned long l; 14959829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned long long ll; 15059829cc1SJean-Christophe PLAGNIOL-VILLARD } cfiword_t; 15159829cc1SJean-Christophe PLAGNIOL-VILLARD 15259829cc1SJean-Christophe PLAGNIOL-VILLARD typedef union { 15359829cc1SJean-Christophe PLAGNIOL-VILLARD volatile unsigned char *cp; 15459829cc1SJean-Christophe PLAGNIOL-VILLARD volatile unsigned short *wp; 15559829cc1SJean-Christophe PLAGNIOL-VILLARD volatile unsigned long *lp; 15659829cc1SJean-Christophe PLAGNIOL-VILLARD volatile unsigned long long *llp; 15759829cc1SJean-Christophe PLAGNIOL-VILLARD } cfiptr_t; 15859829cc1SJean-Christophe PLAGNIOL-VILLARD 15959829cc1SJean-Christophe PLAGNIOL-VILLARD #define NUM_ERASE_REGIONS 4 /* max. number of erase regions */ 16059829cc1SJean-Christophe PLAGNIOL-VILLARD 16159829cc1SJean-Christophe PLAGNIOL-VILLARD static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT }; 16259829cc1SJean-Christophe PLAGNIOL-VILLARD 16359829cc1SJean-Christophe PLAGNIOL-VILLARD /* use CFG_MAX_FLASH_BANKS_DETECT if defined */ 16459829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_MAX_FLASH_BANKS_DETECT 16559829cc1SJean-Christophe PLAGNIOL-VILLARD static ulong bank_base[CFG_MAX_FLASH_BANKS_DETECT] = CFG_FLASH_BANKS_LIST; 16659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */ 16759829cc1SJean-Christophe PLAGNIOL-VILLARD #else 16859829cc1SJean-Christophe PLAGNIOL-VILLARD static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST; 16959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */ 17059829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 17159829cc1SJean-Christophe PLAGNIOL-VILLARD 17259829cc1SJean-Christophe PLAGNIOL-VILLARD /* 17359829cc1SJean-Christophe PLAGNIOL-VILLARD * Check if chip width is defined. If not, start detecting with 8bit. 17459829cc1SJean-Christophe PLAGNIOL-VILLARD */ 17559829cc1SJean-Christophe PLAGNIOL-VILLARD #ifndef CFG_FLASH_CFI_WIDTH 17659829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT 17759829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 17859829cc1SJean-Christophe PLAGNIOL-VILLARD 17959829cc1SJean-Christophe PLAGNIOL-VILLARD typedef unsigned long flash_sect_t; 18059829cc1SJean-Christophe PLAGNIOL-VILLARD 181*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 182*be60a902SHaavard Skinnemoen */ 18359829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE) 184*be60a902SHaavard Skinnemoen static flash_info_t *flash_get_info(ulong base) 185*be60a902SHaavard Skinnemoen { 186*be60a902SHaavard Skinnemoen int i; 187*be60a902SHaavard Skinnemoen flash_info_t * info = 0; 188*be60a902SHaavard Skinnemoen 189*be60a902SHaavard Skinnemoen for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { 190*be60a902SHaavard Skinnemoen info = & flash_info[i]; 191*be60a902SHaavard Skinnemoen if (info->size && info->start[0] <= base && 192*be60a902SHaavard Skinnemoen base <= info->start[0] + info->size - 1) 193*be60a902SHaavard Skinnemoen break; 194*be60a902SHaavard Skinnemoen } 195*be60a902SHaavard Skinnemoen 196*be60a902SHaavard Skinnemoen return i == CFG_MAX_FLASH_BANKS ? 0 : info; 197*be60a902SHaavard Skinnemoen } 19859829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 19959829cc1SJean-Christophe PLAGNIOL-VILLARD 20059829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 20159829cc1SJean-Christophe PLAGNIOL-VILLARD * create an address based on the offset and the port width 20259829cc1SJean-Christophe PLAGNIOL-VILLARD */ 2033055793bSHaavard Skinnemoen static inline uchar * 2047e5b9b47SHaavard Skinnemoen flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset) 20559829cc1SJean-Christophe PLAGNIOL-VILLARD { 20659829cc1SJean-Christophe PLAGNIOL-VILLARD return ((uchar *) (info->start[sect] + (offset * info->portwidth))); 20759829cc1SJean-Christophe PLAGNIOL-VILLARD } 20859829cc1SJean-Christophe PLAGNIOL-VILLARD 209*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 210*be60a902SHaavard Skinnemoen * make a proper sized command based on the port and chip widths 211*be60a902SHaavard Skinnemoen */ 212*be60a902SHaavard Skinnemoen static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf) 213*be60a902SHaavard Skinnemoen { 214*be60a902SHaavard Skinnemoen int i; 215*be60a902SHaavard Skinnemoen uchar *cp = (uchar *) cmdbuf; 216*be60a902SHaavard Skinnemoen 217*be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 218*be60a902SHaavard Skinnemoen for (i = info->portwidth; i > 0; i--) 219*be60a902SHaavard Skinnemoen #else 220*be60a902SHaavard Skinnemoen for (i = 1; i <= info->portwidth; i++) 221*be60a902SHaavard Skinnemoen #endif 222*be60a902SHaavard Skinnemoen *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd; 223*be60a902SHaavard Skinnemoen } 224*be60a902SHaavard Skinnemoen 22559829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 22659829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 22759829cc1SJean-Christophe PLAGNIOL-VILLARD * Debug support 22859829cc1SJean-Christophe PLAGNIOL-VILLARD */ 2293055793bSHaavard Skinnemoen static void print_longlong (char *str, unsigned long long data) 23059829cc1SJean-Christophe PLAGNIOL-VILLARD { 23159829cc1SJean-Christophe PLAGNIOL-VILLARD int i; 23259829cc1SJean-Christophe PLAGNIOL-VILLARD char *cp; 23359829cc1SJean-Christophe PLAGNIOL-VILLARD 23459829cc1SJean-Christophe PLAGNIOL-VILLARD cp = (unsigned char *) &data; 23559829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 8; i++) 23659829cc1SJean-Christophe PLAGNIOL-VILLARD sprintf (&str[i * 2], "%2.2x", *cp++); 23759829cc1SJean-Christophe PLAGNIOL-VILLARD } 238*be60a902SHaavard Skinnemoen 23959829cc1SJean-Christophe PLAGNIOL-VILLARD static void flash_printqry (flash_info_t * info, flash_sect_t sect) 24059829cc1SJean-Christophe PLAGNIOL-VILLARD { 24159829cc1SJean-Christophe PLAGNIOL-VILLARD cfiptr_t cptr; 24259829cc1SJean-Christophe PLAGNIOL-VILLARD int x, y; 24359829cc1SJean-Christophe PLAGNIOL-VILLARD 24459829cc1SJean-Christophe PLAGNIOL-VILLARD for (x = 0; x < 0x40; x += 16U / info->portwidth) { 24559829cc1SJean-Christophe PLAGNIOL-VILLARD cptr.cp = 24659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_make_addr (info, sect, 24759829cc1SJean-Christophe PLAGNIOL-VILLARD x + FLASH_OFFSET_CFI_RESP); 24859829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("%p : ", cptr.cp); 24959829cc1SJean-Christophe PLAGNIOL-VILLARD for (y = 0; y < 16; y++) { 25059829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("%2.2x ", cptr.cp[y]); 25159829cc1SJean-Christophe PLAGNIOL-VILLARD } 25259829cc1SJean-Christophe PLAGNIOL-VILLARD debug (" "); 25359829cc1SJean-Christophe PLAGNIOL-VILLARD for (y = 0; y < 16; y++) { 25459829cc1SJean-Christophe PLAGNIOL-VILLARD if (cptr.cp[y] >= 0x20 && cptr.cp[y] <= 0x7e) { 25559829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("%c", cptr.cp[y]); 25659829cc1SJean-Christophe PLAGNIOL-VILLARD } else { 25759829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("."); 25859829cc1SJean-Christophe PLAGNIOL-VILLARD } 25959829cc1SJean-Christophe PLAGNIOL-VILLARD } 26059829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("\n"); 26159829cc1SJean-Christophe PLAGNIOL-VILLARD } 26259829cc1SJean-Christophe PLAGNIOL-VILLARD } 26359829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 26459829cc1SJean-Christophe PLAGNIOL-VILLARD 26559829cc1SJean-Christophe PLAGNIOL-VILLARD 26659829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 26759829cc1SJean-Christophe PLAGNIOL-VILLARD * read a character at a port width address 26859829cc1SJean-Christophe PLAGNIOL-VILLARD */ 2693055793bSHaavard Skinnemoen static inline uchar flash_read_uchar (flash_info_t * info, uint offset) 27059829cc1SJean-Christophe PLAGNIOL-VILLARD { 27159829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *cp; 27259829cc1SJean-Christophe PLAGNIOL-VILLARD 27359829cc1SJean-Christophe PLAGNIOL-VILLARD cp = flash_make_addr (info, 0, offset); 27459829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 27559829cc1SJean-Christophe PLAGNIOL-VILLARD return (cp[0]); 27659829cc1SJean-Christophe PLAGNIOL-VILLARD #else 27759829cc1SJean-Christophe PLAGNIOL-VILLARD return (cp[info->portwidth - 1]); 27859829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 27959829cc1SJean-Christophe PLAGNIOL-VILLARD } 28059829cc1SJean-Christophe PLAGNIOL-VILLARD 28159829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 28259829cc1SJean-Christophe PLAGNIOL-VILLARD * read a short word by swapping for ppc format. 28359829cc1SJean-Christophe PLAGNIOL-VILLARD */ 2843055793bSHaavard Skinnemoen static ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, 2853055793bSHaavard Skinnemoen uint offset) 28659829cc1SJean-Christophe PLAGNIOL-VILLARD { 28759829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *addr; 28859829cc1SJean-Christophe PLAGNIOL-VILLARD ushort retval; 28959829cc1SJean-Christophe PLAGNIOL-VILLARD 29059829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 29159829cc1SJean-Christophe PLAGNIOL-VILLARD int x; 29259829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 29359829cc1SJean-Christophe PLAGNIOL-VILLARD addr = flash_make_addr (info, sect, offset); 29459829cc1SJean-Christophe PLAGNIOL-VILLARD 29559829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 29659829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("ushort addr is at %p info->portwidth = %d\n", addr, 29759829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth); 29859829cc1SJean-Christophe PLAGNIOL-VILLARD for (x = 0; x < 2 * info->portwidth; x++) { 29959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("addr[%x] = 0x%x\n", x, addr[x]); 30059829cc1SJean-Christophe PLAGNIOL-VILLARD } 30159829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 30259829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 30359829cc1SJean-Christophe PLAGNIOL-VILLARD retval = ((addr[(info->portwidth)] << 8) | addr[0]); 30459829cc1SJean-Christophe PLAGNIOL-VILLARD #else 30559829cc1SJean-Christophe PLAGNIOL-VILLARD retval = ((addr[(2 * info->portwidth) - 1] << 8) | 30659829cc1SJean-Christophe PLAGNIOL-VILLARD addr[info->portwidth - 1]); 30759829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 30859829cc1SJean-Christophe PLAGNIOL-VILLARD 30959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("retval = 0x%x\n", retval); 31059829cc1SJean-Christophe PLAGNIOL-VILLARD return retval; 31159829cc1SJean-Christophe PLAGNIOL-VILLARD } 31259829cc1SJean-Christophe PLAGNIOL-VILLARD 31359829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 31459829cc1SJean-Christophe PLAGNIOL-VILLARD * read a long word by picking the least significant byte of each maximum 31559829cc1SJean-Christophe PLAGNIOL-VILLARD * port size word. Swap for ppc format. 31659829cc1SJean-Christophe PLAGNIOL-VILLARD */ 3173055793bSHaavard Skinnemoen static ulong flash_read_long (flash_info_t * info, flash_sect_t sect, 3183055793bSHaavard Skinnemoen uint offset) 31959829cc1SJean-Christophe PLAGNIOL-VILLARD { 32059829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *addr; 32159829cc1SJean-Christophe PLAGNIOL-VILLARD ulong retval; 32259829cc1SJean-Christophe PLAGNIOL-VILLARD 32359829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 32459829cc1SJean-Christophe PLAGNIOL-VILLARD int x; 32559829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 32659829cc1SJean-Christophe PLAGNIOL-VILLARD addr = flash_make_addr (info, sect, offset); 32759829cc1SJean-Christophe PLAGNIOL-VILLARD 32859829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 32959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("long addr is at %p info->portwidth = %d\n", addr, 33059829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth); 33159829cc1SJean-Christophe PLAGNIOL-VILLARD for (x = 0; x < 4 * info->portwidth; x++) { 33259829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("addr[%x] = 0x%x\n", x, addr[x]); 33359829cc1SJean-Christophe PLAGNIOL-VILLARD } 33459829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 33559829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 33659829cc1SJean-Christophe PLAGNIOL-VILLARD retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) | 3377e5b9b47SHaavard Skinnemoen (addr[(2 * info->portwidth)]) | 3387e5b9b47SHaavard Skinnemoen (addr[(3 * info->portwidth)] << 8); 33959829cc1SJean-Christophe PLAGNIOL-VILLARD #else 34059829cc1SJean-Christophe PLAGNIOL-VILLARD retval = (addr[(2 * info->portwidth) - 1] << 24) | 34159829cc1SJean-Christophe PLAGNIOL-VILLARD (addr[(info->portwidth) - 1] << 16) | 34259829cc1SJean-Christophe PLAGNIOL-VILLARD (addr[(4 * info->portwidth) - 1] << 8) | 34359829cc1SJean-Christophe PLAGNIOL-VILLARD addr[(3 * info->portwidth) - 1]; 34459829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 34559829cc1SJean-Christophe PLAGNIOL-VILLARD return retval; 34659829cc1SJean-Christophe PLAGNIOL-VILLARD } 34759829cc1SJean-Christophe PLAGNIOL-VILLARD 348*be60a902SHaavard Skinnemoen /* 349*be60a902SHaavard Skinnemoen * Write a proper sized command to the correct address 35081b20cccSMichael Schwingen */ 351*be60a902SHaavard Skinnemoen static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, 352*be60a902SHaavard Skinnemoen uint offset, uchar cmd) 35381b20cccSMichael Schwingen { 3547e5b9b47SHaavard Skinnemoen 355*be60a902SHaavard Skinnemoen volatile cfiptr_t addr; 356*be60a902SHaavard Skinnemoen cfiword_t cword; 35781b20cccSMichael Schwingen 358*be60a902SHaavard Skinnemoen addr.cp = flash_make_addr (info, sect, offset); 359*be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 360*be60a902SHaavard Skinnemoen switch (info->portwidth) { 361*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 362*be60a902SHaavard Skinnemoen debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr.cp, cmd, 363*be60a902SHaavard Skinnemoen cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 364*be60a902SHaavard Skinnemoen *addr.cp = cword.c; 365*be60a902SHaavard Skinnemoen break; 366*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 367*be60a902SHaavard Skinnemoen debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr.wp, 368*be60a902SHaavard Skinnemoen cmd, cword.w, 369*be60a902SHaavard Skinnemoen info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 370*be60a902SHaavard Skinnemoen *addr.wp = cword.w; 371*be60a902SHaavard Skinnemoen break; 372*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 373*be60a902SHaavard Skinnemoen debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr.lp, 374*be60a902SHaavard Skinnemoen cmd, cword.l, 375*be60a902SHaavard Skinnemoen info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 376*be60a902SHaavard Skinnemoen *addr.lp = cword.l; 377*be60a902SHaavard Skinnemoen break; 378*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 379*be60a902SHaavard Skinnemoen #ifdef DEBUG 380*be60a902SHaavard Skinnemoen { 381*be60a902SHaavard Skinnemoen char str[20]; 382*be60a902SHaavard Skinnemoen 383*be60a902SHaavard Skinnemoen print_longlong (str, cword.ll); 384*be60a902SHaavard Skinnemoen 385*be60a902SHaavard Skinnemoen debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n", 386*be60a902SHaavard Skinnemoen addr.llp, cmd, str, 387*be60a902SHaavard Skinnemoen info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 38881b20cccSMichael Schwingen } 389*be60a902SHaavard Skinnemoen #endif 390*be60a902SHaavard Skinnemoen *addr.llp = cword.ll; 39181b20cccSMichael Schwingen break; 39281b20cccSMichael Schwingen } 393*be60a902SHaavard Skinnemoen 394*be60a902SHaavard Skinnemoen /* Ensure all the instructions are fully finished */ 395*be60a902SHaavard Skinnemoen sync(); 39681b20cccSMichael Schwingen } 3977e5b9b47SHaavard Skinnemoen 398*be60a902SHaavard Skinnemoen static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect) 399*be60a902SHaavard Skinnemoen { 400*be60a902SHaavard Skinnemoen flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START); 401*be60a902SHaavard Skinnemoen flash_write_cmd (info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK); 402*be60a902SHaavard Skinnemoen } 403*be60a902SHaavard Skinnemoen 404*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 405*be60a902SHaavard Skinnemoen */ 406*be60a902SHaavard Skinnemoen static int flash_isequal (flash_info_t * info, flash_sect_t sect, 407*be60a902SHaavard Skinnemoen uint offset, uchar cmd) 408*be60a902SHaavard Skinnemoen { 409*be60a902SHaavard Skinnemoen cfiptr_t cptr; 410*be60a902SHaavard Skinnemoen cfiword_t cword; 411*be60a902SHaavard Skinnemoen int retval; 412*be60a902SHaavard Skinnemoen 413*be60a902SHaavard Skinnemoen cptr.cp = flash_make_addr (info, sect, offset); 414*be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 415*be60a902SHaavard Skinnemoen 416*be60a902SHaavard Skinnemoen debug ("is= cmd %x(%c) addr %p ", cmd, cmd, cptr.cp); 417*be60a902SHaavard Skinnemoen switch (info->portwidth) { 418*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 419*be60a902SHaavard Skinnemoen debug ("is= %x %x\n", cptr.cp[0], cword.c); 420*be60a902SHaavard Skinnemoen retval = (cptr.cp[0] == cword.c); 421*be60a902SHaavard Skinnemoen break; 422*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 423*be60a902SHaavard Skinnemoen debug ("is= %4.4x %4.4x\n", cptr.wp[0], cword.w); 424*be60a902SHaavard Skinnemoen retval = (cptr.wp[0] == cword.w); 425*be60a902SHaavard Skinnemoen break; 426*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 427*be60a902SHaavard Skinnemoen debug ("is= %8.8lx %8.8lx\n", cptr.lp[0], cword.l); 428*be60a902SHaavard Skinnemoen retval = (cptr.lp[0] == cword.l); 429*be60a902SHaavard Skinnemoen break; 430*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 431*be60a902SHaavard Skinnemoen #ifdef DEBUG 432*be60a902SHaavard Skinnemoen { 433*be60a902SHaavard Skinnemoen char str1[20]; 434*be60a902SHaavard Skinnemoen char str2[20]; 435*be60a902SHaavard Skinnemoen 436*be60a902SHaavard Skinnemoen print_longlong (str1, cptr.llp[0]); 437*be60a902SHaavard Skinnemoen print_longlong (str2, cword.ll); 438*be60a902SHaavard Skinnemoen debug ("is= %s %s\n", str1, str2); 439*be60a902SHaavard Skinnemoen } 440*be60a902SHaavard Skinnemoen #endif 441*be60a902SHaavard Skinnemoen retval = (cptr.llp[0] == cword.ll); 442*be60a902SHaavard Skinnemoen break; 443*be60a902SHaavard Skinnemoen default: 444*be60a902SHaavard Skinnemoen retval = 0; 445*be60a902SHaavard Skinnemoen break; 446*be60a902SHaavard Skinnemoen } 447*be60a902SHaavard Skinnemoen return retval; 448*be60a902SHaavard Skinnemoen } 449*be60a902SHaavard Skinnemoen 450*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 451*be60a902SHaavard Skinnemoen */ 452*be60a902SHaavard Skinnemoen static int flash_isset (flash_info_t * info, flash_sect_t sect, 453*be60a902SHaavard Skinnemoen uint offset, uchar cmd) 454*be60a902SHaavard Skinnemoen { 455*be60a902SHaavard Skinnemoen cfiptr_t cptr; 456*be60a902SHaavard Skinnemoen cfiword_t cword; 457*be60a902SHaavard Skinnemoen int retval; 458*be60a902SHaavard Skinnemoen 459*be60a902SHaavard Skinnemoen cptr.cp = flash_make_addr (info, sect, offset); 460*be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 461*be60a902SHaavard Skinnemoen switch (info->portwidth) { 462*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 463*be60a902SHaavard Skinnemoen retval = ((cptr.cp[0] & cword.c) == cword.c); 464*be60a902SHaavard Skinnemoen break; 465*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 466*be60a902SHaavard Skinnemoen retval = ((cptr.wp[0] & cword.w) == cword.w); 467*be60a902SHaavard Skinnemoen break; 468*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 469*be60a902SHaavard Skinnemoen retval = ((cptr.lp[0] & cword.l) == cword.l); 470*be60a902SHaavard Skinnemoen break; 471*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 472*be60a902SHaavard Skinnemoen retval = ((cptr.llp[0] & cword.ll) == cword.ll); 473*be60a902SHaavard Skinnemoen break; 474*be60a902SHaavard Skinnemoen default: 475*be60a902SHaavard Skinnemoen retval = 0; 476*be60a902SHaavard Skinnemoen break; 477*be60a902SHaavard Skinnemoen } 478*be60a902SHaavard Skinnemoen return retval; 479*be60a902SHaavard Skinnemoen } 480*be60a902SHaavard Skinnemoen 481*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 482*be60a902SHaavard Skinnemoen */ 483*be60a902SHaavard Skinnemoen static int flash_toggle (flash_info_t * info, flash_sect_t sect, 484*be60a902SHaavard Skinnemoen uint offset, uchar cmd) 485*be60a902SHaavard Skinnemoen { 486*be60a902SHaavard Skinnemoen cfiptr_t cptr; 487*be60a902SHaavard Skinnemoen cfiword_t cword; 488*be60a902SHaavard Skinnemoen int retval; 489*be60a902SHaavard Skinnemoen 490*be60a902SHaavard Skinnemoen cptr.cp = flash_make_addr (info, sect, offset); 491*be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 492*be60a902SHaavard Skinnemoen switch (info->portwidth) { 493*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 494*be60a902SHaavard Skinnemoen retval = ((cptr.cp[0] & cword.c) != (cptr.cp[0] & cword.c)); 495*be60a902SHaavard Skinnemoen break; 496*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 497*be60a902SHaavard Skinnemoen retval = ((cptr.wp[0] & cword.w) != (cptr.wp[0] & cword.w)); 498*be60a902SHaavard Skinnemoen break; 499*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 500*be60a902SHaavard Skinnemoen retval = ((cptr.lp[0] & cword.l) != (cptr.lp[0] & cword.l)); 501*be60a902SHaavard Skinnemoen break; 502*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 503*be60a902SHaavard Skinnemoen retval = ((cptr.llp[0] & cword.ll) != 504*be60a902SHaavard Skinnemoen (cptr.llp[0] & cword.ll)); 505*be60a902SHaavard Skinnemoen break; 506*be60a902SHaavard Skinnemoen default: 507*be60a902SHaavard Skinnemoen retval = 0; 508*be60a902SHaavard Skinnemoen break; 509*be60a902SHaavard Skinnemoen } 510*be60a902SHaavard Skinnemoen return retval; 511*be60a902SHaavard Skinnemoen } 512*be60a902SHaavard Skinnemoen 513*be60a902SHaavard Skinnemoen /* 514*be60a902SHaavard Skinnemoen * flash_is_busy - check to see if the flash is busy 515*be60a902SHaavard Skinnemoen * 516*be60a902SHaavard Skinnemoen * This routine checks the status of the chip and returns true if the 517*be60a902SHaavard Skinnemoen * chip is busy. 518*be60a902SHaavard Skinnemoen */ 519*be60a902SHaavard Skinnemoen static int flash_is_busy (flash_info_t * info, flash_sect_t sect) 520*be60a902SHaavard Skinnemoen { 521*be60a902SHaavard Skinnemoen int retval; 522*be60a902SHaavard Skinnemoen 52381b20cccSMichael Schwingen switch (info->vendor) { 52481b20cccSMichael Schwingen case CFI_CMDSET_INTEL_STANDARD: 52581b20cccSMichael Schwingen case CFI_CMDSET_INTEL_EXTENDED: 526*be60a902SHaavard Skinnemoen retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE); 52781b20cccSMichael Schwingen break; 52881b20cccSMichael Schwingen case CFI_CMDSET_AMD_STANDARD: 52981b20cccSMichael Schwingen case CFI_CMDSET_AMD_EXTENDED: 530*be60a902SHaavard Skinnemoen #ifdef CONFIG_FLASH_CFI_LEGACY 53181b20cccSMichael Schwingen case CFI_CMDSET_AMD_LEGACY: 532*be60a902SHaavard Skinnemoen #endif 533*be60a902SHaavard Skinnemoen retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE); 534*be60a902SHaavard Skinnemoen break; 535*be60a902SHaavard Skinnemoen default: 536*be60a902SHaavard Skinnemoen retval = 0; 537*be60a902SHaavard Skinnemoen } 538*be60a902SHaavard Skinnemoen debug ("flash_is_busy: %d\n", retval); 539*be60a902SHaavard Skinnemoen return retval; 540*be60a902SHaavard Skinnemoen } 541*be60a902SHaavard Skinnemoen 542*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 543*be60a902SHaavard Skinnemoen * wait for XSR.7 to be set. Time out with an error if it does not. 544*be60a902SHaavard Skinnemoen * This routine does not set the flash to read-array mode. 545*be60a902SHaavard Skinnemoen */ 546*be60a902SHaavard Skinnemoen static int flash_status_check (flash_info_t * info, flash_sect_t sector, 547*be60a902SHaavard Skinnemoen ulong tout, char *prompt) 548*be60a902SHaavard Skinnemoen { 549*be60a902SHaavard Skinnemoen ulong start; 550*be60a902SHaavard Skinnemoen 551*be60a902SHaavard Skinnemoen #if CFG_HZ != 1000 552*be60a902SHaavard Skinnemoen tout *= CFG_HZ/1000; 553*be60a902SHaavard Skinnemoen #endif 554*be60a902SHaavard Skinnemoen 555*be60a902SHaavard Skinnemoen /* Wait for command completion */ 556*be60a902SHaavard Skinnemoen start = get_timer (0); 557*be60a902SHaavard Skinnemoen while (flash_is_busy (info, sector)) { 558*be60a902SHaavard Skinnemoen if (get_timer (start) > tout) { 559*be60a902SHaavard Skinnemoen printf ("Flash %s timeout at address %lx data %lx\n", 560*be60a902SHaavard Skinnemoen prompt, info->start[sector], 561*be60a902SHaavard Skinnemoen flash_read_long (info, sector, 0)); 562*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, info->cmd_reset); 563*be60a902SHaavard Skinnemoen return ERR_TIMOUT; 564*be60a902SHaavard Skinnemoen } 565*be60a902SHaavard Skinnemoen udelay (1); /* also triggers watchdog */ 566*be60a902SHaavard Skinnemoen } 567*be60a902SHaavard Skinnemoen return ERR_OK; 568*be60a902SHaavard Skinnemoen } 569*be60a902SHaavard Skinnemoen 570*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 571*be60a902SHaavard Skinnemoen * Wait for XSR.7 to be set, if it times out print an error, otherwise 572*be60a902SHaavard Skinnemoen * do a full status check. 573*be60a902SHaavard Skinnemoen * 574*be60a902SHaavard Skinnemoen * This routine sets the flash to read-array mode. 575*be60a902SHaavard Skinnemoen */ 576*be60a902SHaavard Skinnemoen static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, 577*be60a902SHaavard Skinnemoen ulong tout, char *prompt) 578*be60a902SHaavard Skinnemoen { 579*be60a902SHaavard Skinnemoen int retcode; 580*be60a902SHaavard Skinnemoen 581*be60a902SHaavard Skinnemoen retcode = flash_status_check (info, sector, tout, prompt); 582*be60a902SHaavard Skinnemoen switch (info->vendor) { 583*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 584*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 585*be60a902SHaavard Skinnemoen if ((retcode == ERR_OK) 586*be60a902SHaavard Skinnemoen && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) { 587*be60a902SHaavard Skinnemoen retcode = ERR_INVAL; 588*be60a902SHaavard Skinnemoen printf ("Flash %s error at address %lx\n", prompt, 589*be60a902SHaavard Skinnemoen info->start[sector]); 590*be60a902SHaavard Skinnemoen if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | 591*be60a902SHaavard Skinnemoen FLASH_STATUS_PSLBS)) { 592*be60a902SHaavard Skinnemoen puts ("Command Sequence Error.\n"); 593*be60a902SHaavard Skinnemoen } else if (flash_isset (info, sector, 0, 594*be60a902SHaavard Skinnemoen FLASH_STATUS_ECLBS)) { 595*be60a902SHaavard Skinnemoen puts ("Block Erase Error.\n"); 596*be60a902SHaavard Skinnemoen retcode = ERR_NOT_ERASED; 597*be60a902SHaavard Skinnemoen } else if (flash_isset (info, sector, 0, 598*be60a902SHaavard Skinnemoen FLASH_STATUS_PSLBS)) { 599*be60a902SHaavard Skinnemoen puts ("Locking Error\n"); 600*be60a902SHaavard Skinnemoen } 601*be60a902SHaavard Skinnemoen if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) { 602*be60a902SHaavard Skinnemoen puts ("Block locked.\n"); 603*be60a902SHaavard Skinnemoen retcode = ERR_PROTECTED; 604*be60a902SHaavard Skinnemoen } 605*be60a902SHaavard Skinnemoen if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS)) 606*be60a902SHaavard Skinnemoen puts ("Vpp Low Error.\n"); 607*be60a902SHaavard Skinnemoen } 608*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, info->cmd_reset); 609*be60a902SHaavard Skinnemoen break; 610*be60a902SHaavard Skinnemoen default: 61181b20cccSMichael Schwingen break; 61281b20cccSMichael Schwingen } 613*be60a902SHaavard Skinnemoen return retcode; 61481b20cccSMichael Schwingen } 615*be60a902SHaavard Skinnemoen 616*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 617*be60a902SHaavard Skinnemoen */ 618*be60a902SHaavard Skinnemoen static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) 619*be60a902SHaavard Skinnemoen { 620*be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 621*be60a902SHaavard Skinnemoen unsigned short w; 622*be60a902SHaavard Skinnemoen unsigned int l; 623*be60a902SHaavard Skinnemoen unsigned long long ll; 624*be60a902SHaavard Skinnemoen #endif 625*be60a902SHaavard Skinnemoen 626*be60a902SHaavard Skinnemoen switch (info->portwidth) { 627*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 628*be60a902SHaavard Skinnemoen cword->c = c; 629*be60a902SHaavard Skinnemoen break; 630*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 631*be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 632*be60a902SHaavard Skinnemoen w = c; 633*be60a902SHaavard Skinnemoen w <<= 8; 634*be60a902SHaavard Skinnemoen cword->w = (cword->w >> 8) | w; 63581b20cccSMichael Schwingen #else 636*be60a902SHaavard Skinnemoen cword->w = (cword->w << 8) | c; 637*be60a902SHaavard Skinnemoen #endif 638*be60a902SHaavard Skinnemoen break; 639*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 640*be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 641*be60a902SHaavard Skinnemoen l = c; 642*be60a902SHaavard Skinnemoen l <<= 24; 643*be60a902SHaavard Skinnemoen cword->l = (cword->l >> 8) | l; 644*be60a902SHaavard Skinnemoen #else 645*be60a902SHaavard Skinnemoen cword->l = (cword->l << 8) | c; 646*be60a902SHaavard Skinnemoen #endif 647*be60a902SHaavard Skinnemoen break; 648*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 649*be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 650*be60a902SHaavard Skinnemoen ll = c; 651*be60a902SHaavard Skinnemoen ll <<= 56; 652*be60a902SHaavard Skinnemoen cword->ll = (cword->ll >> 8) | ll; 653*be60a902SHaavard Skinnemoen #else 654*be60a902SHaavard Skinnemoen cword->ll = (cword->ll << 8) | c; 655*be60a902SHaavard Skinnemoen #endif 656*be60a902SHaavard Skinnemoen break; 657*be60a902SHaavard Skinnemoen } 658*be60a902SHaavard Skinnemoen } 659*be60a902SHaavard Skinnemoen 660*be60a902SHaavard Skinnemoen /* loop through the sectors from the highest address when the passed 661*be60a902SHaavard Skinnemoen * address is greater or equal to the sector address we have a match 662*be60a902SHaavard Skinnemoen */ 663*be60a902SHaavard Skinnemoen static flash_sect_t find_sector (flash_info_t * info, ulong addr) 66481b20cccSMichael Schwingen { 665*be60a902SHaavard Skinnemoen flash_sect_t sector; 666*be60a902SHaavard Skinnemoen 667*be60a902SHaavard Skinnemoen for (sector = info->sector_count - 1; sector >= 0; sector--) { 668*be60a902SHaavard Skinnemoen if (addr >= info->start[sector]) 669*be60a902SHaavard Skinnemoen break; 67081b20cccSMichael Schwingen } 671*be60a902SHaavard Skinnemoen return sector; 67259829cc1SJean-Christophe PLAGNIOL-VILLARD } 67359829cc1SJean-Christophe PLAGNIOL-VILLARD 67459829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 67559829cc1SJean-Christophe PLAGNIOL-VILLARD */ 676*be60a902SHaavard Skinnemoen static int flash_write_cfiword (flash_info_t * info, ulong dest, 677*be60a902SHaavard Skinnemoen cfiword_t cword) 67859829cc1SJean-Christophe PLAGNIOL-VILLARD { 679*be60a902SHaavard Skinnemoen cfiptr_t ctladdr; 680*be60a902SHaavard Skinnemoen cfiptr_t cptr; 681*be60a902SHaavard Skinnemoen int flag; 68259829cc1SJean-Christophe PLAGNIOL-VILLARD 683*be60a902SHaavard Skinnemoen ctladdr.cp = flash_make_addr (info, 0, 0); 684*be60a902SHaavard Skinnemoen cptr.cp = (uchar *) dest; 685*be60a902SHaavard Skinnemoen 686*be60a902SHaavard Skinnemoen /* Check if Flash is (sufficiently) erased */ 687*be60a902SHaavard Skinnemoen switch (info->portwidth) { 688*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 689*be60a902SHaavard Skinnemoen flag = ((cptr.cp[0] & cword.c) == cword.c); 690*be60a902SHaavard Skinnemoen break; 691*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 692*be60a902SHaavard Skinnemoen flag = ((cptr.wp[0] & cword.w) == cword.w); 693*be60a902SHaavard Skinnemoen break; 694*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 695*be60a902SHaavard Skinnemoen flag = ((cptr.lp[0] & cword.l) == cword.l); 696*be60a902SHaavard Skinnemoen break; 697*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 698*be60a902SHaavard Skinnemoen flag = ((cptr.llp[0] & cword.ll) == cword.ll); 699*be60a902SHaavard Skinnemoen break; 700*be60a902SHaavard Skinnemoen default: 701*be60a902SHaavard Skinnemoen return 2; 702*be60a902SHaavard Skinnemoen } 703*be60a902SHaavard Skinnemoen if (!flag) 704*be60a902SHaavard Skinnemoen return 2; 705*be60a902SHaavard Skinnemoen 706*be60a902SHaavard Skinnemoen /* Disable interrupts which might cause a timeout here */ 707*be60a902SHaavard Skinnemoen flag = disable_interrupts (); 708*be60a902SHaavard Skinnemoen 709*be60a902SHaavard Skinnemoen switch (info->vendor) { 710*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 711*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 712*be60a902SHaavard Skinnemoen flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS); 713*be60a902SHaavard Skinnemoen flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE); 714*be60a902SHaavard Skinnemoen break; 715*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_EXTENDED: 716*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_STANDARD: 717*be60a902SHaavard Skinnemoen #ifdef CONFIG_FLASH_CFI_LEGACY 718*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_LEGACY: 719*be60a902SHaavard Skinnemoen #endif 720*be60a902SHaavard Skinnemoen flash_unlock_seq (info, 0); 721*be60a902SHaavard Skinnemoen flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE); 72259829cc1SJean-Christophe PLAGNIOL-VILLARD break; 72359829cc1SJean-Christophe PLAGNIOL-VILLARD } 72459829cc1SJean-Christophe PLAGNIOL-VILLARD 725*be60a902SHaavard Skinnemoen switch (info->portwidth) { 726*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 727*be60a902SHaavard Skinnemoen cptr.cp[0] = cword.c; 728*be60a902SHaavard Skinnemoen break; 729*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 730*be60a902SHaavard Skinnemoen cptr.wp[0] = cword.w; 731*be60a902SHaavard Skinnemoen break; 732*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 733*be60a902SHaavard Skinnemoen cptr.lp[0] = cword.l; 734*be60a902SHaavard Skinnemoen break; 735*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 736*be60a902SHaavard Skinnemoen cptr.llp[0] = cword.ll; 737*be60a902SHaavard Skinnemoen break; 73859829cc1SJean-Christophe PLAGNIOL-VILLARD } 739*be60a902SHaavard Skinnemoen 740*be60a902SHaavard Skinnemoen /* re-enable interrupts if necessary */ 741*be60a902SHaavard Skinnemoen if (flag) 742*be60a902SHaavard Skinnemoen enable_interrupts (); 743*be60a902SHaavard Skinnemoen 744*be60a902SHaavard Skinnemoen return flash_full_status_check (info, find_sector (info, dest), 745*be60a902SHaavard Skinnemoen info->write_tout, "write"); 746*be60a902SHaavard Skinnemoen } 747*be60a902SHaavard Skinnemoen 748*be60a902SHaavard Skinnemoen #ifdef CFG_FLASH_USE_BUFFER_WRITE 749*be60a902SHaavard Skinnemoen 750*be60a902SHaavard Skinnemoen static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, 751*be60a902SHaavard Skinnemoen int len) 752*be60a902SHaavard Skinnemoen { 753*be60a902SHaavard Skinnemoen flash_sect_t sector; 754*be60a902SHaavard Skinnemoen int cnt; 755*be60a902SHaavard Skinnemoen int retcode; 756*be60a902SHaavard Skinnemoen volatile cfiptr_t src; 757*be60a902SHaavard Skinnemoen volatile cfiptr_t dst; 758*be60a902SHaavard Skinnemoen 759*be60a902SHaavard Skinnemoen switch (info->vendor) { 760*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 761*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 762*be60a902SHaavard Skinnemoen src.cp = cp; 763*be60a902SHaavard Skinnemoen dst.cp = (uchar *) dest; 764*be60a902SHaavard Skinnemoen sector = find_sector (info, dest); 765*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); 766*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); 767*be60a902SHaavard Skinnemoen retcode = flash_status_check (info, sector, 768*be60a902SHaavard Skinnemoen info->buffer_write_tout, 769*be60a902SHaavard Skinnemoen "write to buffer"); 770*be60a902SHaavard Skinnemoen if (retcode == ERR_OK) { 771*be60a902SHaavard Skinnemoen /* reduce the number of loops by the width of 772*be60a902SHaavard Skinnemoen * the port */ 773*be60a902SHaavard Skinnemoen switch (info->portwidth) { 774*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 775*be60a902SHaavard Skinnemoen cnt = len; 776*be60a902SHaavard Skinnemoen break; 777*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 778*be60a902SHaavard Skinnemoen cnt = len >> 1; 779*be60a902SHaavard Skinnemoen break; 780*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 781*be60a902SHaavard Skinnemoen cnt = len >> 2; 782*be60a902SHaavard Skinnemoen break; 783*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 784*be60a902SHaavard Skinnemoen cnt = len >> 3; 785*be60a902SHaavard Skinnemoen break; 786*be60a902SHaavard Skinnemoen default: 787*be60a902SHaavard Skinnemoen return ERR_INVAL; 788*be60a902SHaavard Skinnemoen break; 789*be60a902SHaavard Skinnemoen } 790*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 791*be60a902SHaavard Skinnemoen while (cnt-- > 0) { 792*be60a902SHaavard Skinnemoen switch (info->portwidth) { 793*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 794*be60a902SHaavard Skinnemoen *dst.cp++ = *src.cp++; 795*be60a902SHaavard Skinnemoen break; 796*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 797*be60a902SHaavard Skinnemoen *dst.wp++ = *src.wp++; 798*be60a902SHaavard Skinnemoen break; 799*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 800*be60a902SHaavard Skinnemoen *dst.lp++ = *src.lp++; 801*be60a902SHaavard Skinnemoen break; 802*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 803*be60a902SHaavard Skinnemoen *dst.llp++ = *src.llp++; 804*be60a902SHaavard Skinnemoen break; 805*be60a902SHaavard Skinnemoen default: 806*be60a902SHaavard Skinnemoen return ERR_INVAL; 807*be60a902SHaavard Skinnemoen break; 808*be60a902SHaavard Skinnemoen } 809*be60a902SHaavard Skinnemoen } 810*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, 811*be60a902SHaavard Skinnemoen FLASH_CMD_WRITE_BUFFER_CONFIRM); 812*be60a902SHaavard Skinnemoen retcode = flash_full_status_check ( 813*be60a902SHaavard Skinnemoen info, sector, info->buffer_write_tout, 814*be60a902SHaavard Skinnemoen "buffer write"); 815*be60a902SHaavard Skinnemoen } 816*be60a902SHaavard Skinnemoen return retcode; 817*be60a902SHaavard Skinnemoen 818*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_STANDARD: 819*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_EXTENDED: 820*be60a902SHaavard Skinnemoen src.cp = cp; 821*be60a902SHaavard Skinnemoen dst.cp = (uchar *) dest; 822*be60a902SHaavard Skinnemoen sector = find_sector (info, dest); 823*be60a902SHaavard Skinnemoen 824*be60a902SHaavard Skinnemoen flash_unlock_seq(info,0); 825*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER); 826*be60a902SHaavard Skinnemoen 827*be60a902SHaavard Skinnemoen switch (info->portwidth) { 828*be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 829*be60a902SHaavard Skinnemoen cnt = len; 830*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 831*be60a902SHaavard Skinnemoen while (cnt-- > 0) *dst.cp++ = *src.cp++; 832*be60a902SHaavard Skinnemoen break; 833*be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 834*be60a902SHaavard Skinnemoen cnt = len >> 1; 835*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 836*be60a902SHaavard Skinnemoen while (cnt-- > 0) *dst.wp++ = *src.wp++; 837*be60a902SHaavard Skinnemoen break; 838*be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 839*be60a902SHaavard Skinnemoen cnt = len >> 2; 840*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 841*be60a902SHaavard Skinnemoen while (cnt-- > 0) *dst.lp++ = *src.lp++; 842*be60a902SHaavard Skinnemoen break; 843*be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 844*be60a902SHaavard Skinnemoen cnt = len >> 3; 845*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 846*be60a902SHaavard Skinnemoen while (cnt-- > 0) *dst.llp++ = *src.llp++; 847*be60a902SHaavard Skinnemoen break; 848*be60a902SHaavard Skinnemoen default: 849*be60a902SHaavard Skinnemoen return ERR_INVAL; 850*be60a902SHaavard Skinnemoen } 851*be60a902SHaavard Skinnemoen 852*be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); 853*be60a902SHaavard Skinnemoen retcode = flash_full_status_check (info, sector, 854*be60a902SHaavard Skinnemoen info->buffer_write_tout, 855*be60a902SHaavard Skinnemoen "buffer write"); 856*be60a902SHaavard Skinnemoen return retcode; 857*be60a902SHaavard Skinnemoen 858*be60a902SHaavard Skinnemoen default: 859*be60a902SHaavard Skinnemoen debug ("Unknown Command Set\n"); 860*be60a902SHaavard Skinnemoen return ERR_INVAL; 861*be60a902SHaavard Skinnemoen } 862*be60a902SHaavard Skinnemoen } 863*be60a902SHaavard Skinnemoen #endif /* CFG_FLASH_USE_BUFFER_WRITE */ 864*be60a902SHaavard Skinnemoen 86559829cc1SJean-Christophe PLAGNIOL-VILLARD 86659829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 86759829cc1SJean-Christophe PLAGNIOL-VILLARD */ 86859829cc1SJean-Christophe PLAGNIOL-VILLARD int flash_erase (flash_info_t * info, int s_first, int s_last) 86959829cc1SJean-Christophe PLAGNIOL-VILLARD { 87059829cc1SJean-Christophe PLAGNIOL-VILLARD int rcode = 0; 87159829cc1SJean-Christophe PLAGNIOL-VILLARD int prot; 87259829cc1SJean-Christophe PLAGNIOL-VILLARD flash_sect_t sect; 87359829cc1SJean-Christophe PLAGNIOL-VILLARD 87459829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->flash_id != FLASH_MAN_CFI) { 87559829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("Can't erase unknown flash type - aborted\n"); 87659829cc1SJean-Christophe PLAGNIOL-VILLARD return 1; 87759829cc1SJean-Christophe PLAGNIOL-VILLARD } 87859829cc1SJean-Christophe PLAGNIOL-VILLARD if ((s_first < 0) || (s_first > s_last)) { 87959829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("- no sectors to erase\n"); 88059829cc1SJean-Christophe PLAGNIOL-VILLARD return 1; 88159829cc1SJean-Christophe PLAGNIOL-VILLARD } 88259829cc1SJean-Christophe PLAGNIOL-VILLARD 88359829cc1SJean-Christophe PLAGNIOL-VILLARD prot = 0; 88459829cc1SJean-Christophe PLAGNIOL-VILLARD for (sect = s_first; sect <= s_last; ++sect) { 88559829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->protect[sect]) { 88659829cc1SJean-Christophe PLAGNIOL-VILLARD prot++; 88759829cc1SJean-Christophe PLAGNIOL-VILLARD } 88859829cc1SJean-Christophe PLAGNIOL-VILLARD } 88959829cc1SJean-Christophe PLAGNIOL-VILLARD if (prot) { 8907e5b9b47SHaavard Skinnemoen printf ("- Warning: %d protected sectors will not be erased!\n", 8917e5b9b47SHaavard Skinnemoen prot); 89259829cc1SJean-Christophe PLAGNIOL-VILLARD } else { 89359829cc1SJean-Christophe PLAGNIOL-VILLARD putc ('\n'); 89459829cc1SJean-Christophe PLAGNIOL-VILLARD } 89559829cc1SJean-Christophe PLAGNIOL-VILLARD 89659829cc1SJean-Christophe PLAGNIOL-VILLARD 89759829cc1SJean-Christophe PLAGNIOL-VILLARD for (sect = s_first; sect <= s_last; sect++) { 89859829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->protect[sect] == 0) { /* not protected */ 89959829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 90059829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 90159829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 9027e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9037e5b9b47SHaavard Skinnemoen FLASH_CMD_CLEAR_STATUS); 9047e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9057e5b9b47SHaavard Skinnemoen FLASH_CMD_BLOCK_ERASE); 9067e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9077e5b9b47SHaavard Skinnemoen FLASH_CMD_ERASE_CONFIRM); 90859829cc1SJean-Christophe PLAGNIOL-VILLARD break; 90959829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 91059829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 91159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_unlock_seq (info, sect); 9127e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 9137e5b9b47SHaavard Skinnemoen info->addr_unlock1, 9147e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_START); 91559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_unlock_seq (info, sect); 9167e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9177e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_SECTOR); 91859829cc1SJean-Christophe PLAGNIOL-VILLARD break; 91981b20cccSMichael Schwingen #ifdef CONFIG_FLASH_CFI_LEGACY 92081b20cccSMichael Schwingen case CFI_CMDSET_AMD_LEGACY: 92181b20cccSMichael Schwingen flash_unlock_seq (info, 0); 9227e5b9b47SHaavard Skinnemoen flash_write_cmd (info, 0, info->addr_unlock1, 9237e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_START); 92481b20cccSMichael Schwingen flash_unlock_seq (info, 0); 9257e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9267e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_SECTOR); 92781b20cccSMichael Schwingen break; 92881b20cccSMichael Schwingen #endif 92959829cc1SJean-Christophe PLAGNIOL-VILLARD default: 93059829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("Unkown flash vendor %d\n", 93159829cc1SJean-Christophe PLAGNIOL-VILLARD info->vendor); 93259829cc1SJean-Christophe PLAGNIOL-VILLARD break; 93359829cc1SJean-Christophe PLAGNIOL-VILLARD } 93459829cc1SJean-Christophe PLAGNIOL-VILLARD 93559829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_full_status_check 93659829cc1SJean-Christophe PLAGNIOL-VILLARD (info, sect, info->erase_blk_tout, "erase")) { 93759829cc1SJean-Christophe PLAGNIOL-VILLARD rcode = 1; 93859829cc1SJean-Christophe PLAGNIOL-VILLARD } else 93959829cc1SJean-Christophe PLAGNIOL-VILLARD putc ('.'); 94059829cc1SJean-Christophe PLAGNIOL-VILLARD } 94159829cc1SJean-Christophe PLAGNIOL-VILLARD } 94259829cc1SJean-Christophe PLAGNIOL-VILLARD puts (" done\n"); 94359829cc1SJean-Christophe PLAGNIOL-VILLARD return rcode; 94459829cc1SJean-Christophe PLAGNIOL-VILLARD } 94559829cc1SJean-Christophe PLAGNIOL-VILLARD 94659829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 94759829cc1SJean-Christophe PLAGNIOL-VILLARD */ 94859829cc1SJean-Christophe PLAGNIOL-VILLARD void flash_print_info (flash_info_t * info) 94959829cc1SJean-Christophe PLAGNIOL-VILLARD { 95059829cc1SJean-Christophe PLAGNIOL-VILLARD int i; 95159829cc1SJean-Christophe PLAGNIOL-VILLARD 95259829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->flash_id != FLASH_MAN_CFI) { 95359829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("missing or unknown FLASH type\n"); 95459829cc1SJean-Christophe PLAGNIOL-VILLARD return; 95559829cc1SJean-Christophe PLAGNIOL-VILLARD } 95659829cc1SJean-Christophe PLAGNIOL-VILLARD 95781b20cccSMichael Schwingen printf ("%s FLASH (%d x %d)", 95881b20cccSMichael Schwingen info->name, 95959829cc1SJean-Christophe PLAGNIOL-VILLARD (info->portwidth << 3), (info->chipwidth << 3)); 96081b20cccSMichael Schwingen if (info->size < 1024*1024) 96181b20cccSMichael Schwingen printf (" Size: %ld kB in %d Sectors\n", 96281b20cccSMichael Schwingen info->size >> 10, info->sector_count); 96381b20cccSMichael Schwingen else 96459829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" Size: %ld MB in %d Sectors\n", 96559829cc1SJean-Christophe PLAGNIOL-VILLARD info->size >> 20, info->sector_count); 96659829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" "); 96759829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 96859829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 96959829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("Intel Standard"); 97059829cc1SJean-Christophe PLAGNIOL-VILLARD break; 97159829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 97259829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("Intel Extended"); 97359829cc1SJean-Christophe PLAGNIOL-VILLARD break; 97459829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 97559829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("AMD Standard"); 97659829cc1SJean-Christophe PLAGNIOL-VILLARD break; 97759829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 97859829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("AMD Extended"); 97959829cc1SJean-Christophe PLAGNIOL-VILLARD break; 98081b20cccSMichael Schwingen #ifdef CONFIG_FLASH_CFI_LEGACY 98181b20cccSMichael Schwingen case CFI_CMDSET_AMD_LEGACY: 98281b20cccSMichael Schwingen printf ("AMD Legacy"); 98381b20cccSMichael Schwingen break; 98481b20cccSMichael Schwingen #endif 98559829cc1SJean-Christophe PLAGNIOL-VILLARD default: 98659829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("Unknown (%d)", info->vendor); 98759829cc1SJean-Christophe PLAGNIOL-VILLARD break; 98859829cc1SJean-Christophe PLAGNIOL-VILLARD } 98959829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X", 99059829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id, info->device_id); 99159829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->device_id == 0x7E) { 99259829cc1SJean-Christophe PLAGNIOL-VILLARD printf("%04X", info->device_id2); 99359829cc1SJean-Christophe PLAGNIOL-VILLARD } 99459829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("\n Erase timeout: %ld ms, write timeout: %ld ms\n", 99559829cc1SJean-Christophe PLAGNIOL-VILLARD info->erase_blk_tout, 99659829cc1SJean-Christophe PLAGNIOL-VILLARD info->write_tout); 99759829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->buffer_size > 1) { 9987e5b9b47SHaavard Skinnemoen printf (" Buffer write timeout: %ld ms, " 9997e5b9b47SHaavard Skinnemoen "buffer size: %d bytes\n", 100059829cc1SJean-Christophe PLAGNIOL-VILLARD info->buffer_write_tout, 100159829cc1SJean-Christophe PLAGNIOL-VILLARD info->buffer_size); 100259829cc1SJean-Christophe PLAGNIOL-VILLARD } 100359829cc1SJean-Christophe PLAGNIOL-VILLARD 100459829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("\n Sector Start Addresses:"); 100559829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->sector_count; ++i) { 100659829cc1SJean-Christophe PLAGNIOL-VILLARD if ((i % 5) == 0) 100759829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("\n"); 100859829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_EMPTY_INFO 100959829cc1SJean-Christophe PLAGNIOL-VILLARD int k; 101059829cc1SJean-Christophe PLAGNIOL-VILLARD int size; 101159829cc1SJean-Christophe PLAGNIOL-VILLARD int erased; 101259829cc1SJean-Christophe PLAGNIOL-VILLARD volatile unsigned long *flash; 101359829cc1SJean-Christophe PLAGNIOL-VILLARD 101459829cc1SJean-Christophe PLAGNIOL-VILLARD /* 101559829cc1SJean-Christophe PLAGNIOL-VILLARD * Check if whole sector is erased 101659829cc1SJean-Christophe PLAGNIOL-VILLARD */ 101759829cc1SJean-Christophe PLAGNIOL-VILLARD if (i != (info->sector_count - 1)) 101859829cc1SJean-Christophe PLAGNIOL-VILLARD size = info->start[i + 1] - info->start[i]; 101959829cc1SJean-Christophe PLAGNIOL-VILLARD else 102059829cc1SJean-Christophe PLAGNIOL-VILLARD size = info->start[0] + info->size - info->start[i]; 102159829cc1SJean-Christophe PLAGNIOL-VILLARD erased = 1; 102259829cc1SJean-Christophe PLAGNIOL-VILLARD flash = (volatile unsigned long *) info->start[i]; 102359829cc1SJean-Christophe PLAGNIOL-VILLARD size = size >> 2; /* divide by 4 for longword access */ 102459829cc1SJean-Christophe PLAGNIOL-VILLARD for (k = 0; k < size; k++) { 102559829cc1SJean-Christophe PLAGNIOL-VILLARD if (*flash++ != 0xffffffff) { 102659829cc1SJean-Christophe PLAGNIOL-VILLARD erased = 0; 102759829cc1SJean-Christophe PLAGNIOL-VILLARD break; 102859829cc1SJean-Christophe PLAGNIOL-VILLARD } 102959829cc1SJean-Christophe PLAGNIOL-VILLARD } 103059829cc1SJean-Christophe PLAGNIOL-VILLARD 103159829cc1SJean-Christophe PLAGNIOL-VILLARD /* print empty and read-only info */ 103259829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" %08lX %c %s ", 103359829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[i], 103459829cc1SJean-Christophe PLAGNIOL-VILLARD erased ? 'E' : ' ', 103559829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[i] ? "RO" : " "); 103659829cc1SJean-Christophe PLAGNIOL-VILLARD #else /* ! CFG_FLASH_EMPTY_INFO */ 103759829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" %08lX %s ", 103859829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[i], 103959829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[i] ? "RO" : " "); 104059829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 104159829cc1SJean-Christophe PLAGNIOL-VILLARD } 104259829cc1SJean-Christophe PLAGNIOL-VILLARD putc ('\n'); 104359829cc1SJean-Christophe PLAGNIOL-VILLARD return; 104459829cc1SJean-Christophe PLAGNIOL-VILLARD } 104559829cc1SJean-Christophe PLAGNIOL-VILLARD 104659829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 104759829cc1SJean-Christophe PLAGNIOL-VILLARD * Copy memory to flash, returns: 104859829cc1SJean-Christophe PLAGNIOL-VILLARD * 0 - OK 104959829cc1SJean-Christophe PLAGNIOL-VILLARD * 1 - write timeout 105059829cc1SJean-Christophe PLAGNIOL-VILLARD * 2 - Flash not erased 105159829cc1SJean-Christophe PLAGNIOL-VILLARD */ 105259829cc1SJean-Christophe PLAGNIOL-VILLARD int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) 105359829cc1SJean-Christophe PLAGNIOL-VILLARD { 105459829cc1SJean-Christophe PLAGNIOL-VILLARD ulong wp; 105559829cc1SJean-Christophe PLAGNIOL-VILLARD ulong cp; 105659829cc1SJean-Christophe PLAGNIOL-VILLARD int aln; 105759829cc1SJean-Christophe PLAGNIOL-VILLARD cfiword_t cword; 105859829cc1SJean-Christophe PLAGNIOL-VILLARD int i, rc; 105959829cc1SJean-Christophe PLAGNIOL-VILLARD 106059829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_USE_BUFFER_WRITE 106159829cc1SJean-Christophe PLAGNIOL-VILLARD int buffered_size; 106259829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 106359829cc1SJean-Christophe PLAGNIOL-VILLARD /* get lower aligned address */ 106459829cc1SJean-Christophe PLAGNIOL-VILLARD /* get lower aligned address */ 106559829cc1SJean-Christophe PLAGNIOL-VILLARD wp = (addr & ~(info->portwidth - 1)); 106659829cc1SJean-Christophe PLAGNIOL-VILLARD 106759829cc1SJean-Christophe PLAGNIOL-VILLARD /* handle unaligned start */ 106859829cc1SJean-Christophe PLAGNIOL-VILLARD if ((aln = addr - wp) != 0) { 106959829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 107059829cc1SJean-Christophe PLAGNIOL-VILLARD cp = wp; 107159829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < aln; ++i, ++cp) 107259829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, (*(uchar *) cp)); 107359829cc1SJean-Christophe PLAGNIOL-VILLARD 107459829cc1SJean-Christophe PLAGNIOL-VILLARD for (; (i < info->portwidth) && (cnt > 0); i++) { 107559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 107659829cc1SJean-Christophe PLAGNIOL-VILLARD cnt--; 107759829cc1SJean-Christophe PLAGNIOL-VILLARD cp++; 107859829cc1SJean-Christophe PLAGNIOL-VILLARD } 107959829cc1SJean-Christophe PLAGNIOL-VILLARD for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp) 108059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, (*(uchar *) cp)); 108159829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfiword (info, wp, cword)) != 0) 108259829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 108359829cc1SJean-Christophe PLAGNIOL-VILLARD wp = cp; 108459829cc1SJean-Christophe PLAGNIOL-VILLARD } 108559829cc1SJean-Christophe PLAGNIOL-VILLARD 108659829cc1SJean-Christophe PLAGNIOL-VILLARD /* handle the aligned part */ 108759829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_USE_BUFFER_WRITE 108859829cc1SJean-Christophe PLAGNIOL-VILLARD buffered_size = (info->portwidth / info->chipwidth); 108959829cc1SJean-Christophe PLAGNIOL-VILLARD buffered_size *= info->buffer_size; 109059829cc1SJean-Christophe PLAGNIOL-VILLARD while (cnt >= info->portwidth) { 109159829cc1SJean-Christophe PLAGNIOL-VILLARD /* prohibit buffer write when buffer_size is 1 */ 109259829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->buffer_size == 1) { 109359829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 109459829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->portwidth; i++) 109559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 109659829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfiword (info, wp, cword)) != 0) 109759829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 109859829cc1SJean-Christophe PLAGNIOL-VILLARD wp += info->portwidth; 109959829cc1SJean-Christophe PLAGNIOL-VILLARD cnt -= info->portwidth; 110059829cc1SJean-Christophe PLAGNIOL-VILLARD continue; 110159829cc1SJean-Christophe PLAGNIOL-VILLARD } 110259829cc1SJean-Christophe PLAGNIOL-VILLARD 110359829cc1SJean-Christophe PLAGNIOL-VILLARD /* write buffer until next buffered_size aligned boundary */ 110459829cc1SJean-Christophe PLAGNIOL-VILLARD i = buffered_size - (wp % buffered_size); 110559829cc1SJean-Christophe PLAGNIOL-VILLARD if (i > cnt) 110659829cc1SJean-Christophe PLAGNIOL-VILLARD i = cnt; 110759829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK) 110859829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 110959829cc1SJean-Christophe PLAGNIOL-VILLARD i -= i & (info->portwidth - 1); 111059829cc1SJean-Christophe PLAGNIOL-VILLARD wp += i; 111159829cc1SJean-Christophe PLAGNIOL-VILLARD src += i; 111259829cc1SJean-Christophe PLAGNIOL-VILLARD cnt -= i; 111359829cc1SJean-Christophe PLAGNIOL-VILLARD } 111459829cc1SJean-Christophe PLAGNIOL-VILLARD #else 111559829cc1SJean-Christophe PLAGNIOL-VILLARD while (cnt >= info->portwidth) { 111659829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 111759829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->portwidth; i++) { 111859829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 111959829cc1SJean-Christophe PLAGNIOL-VILLARD } 112059829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfiword (info, wp, cword)) != 0) 112159829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 112259829cc1SJean-Christophe PLAGNIOL-VILLARD wp += info->portwidth; 112359829cc1SJean-Christophe PLAGNIOL-VILLARD cnt -= info->portwidth; 112459829cc1SJean-Christophe PLAGNIOL-VILLARD } 112559829cc1SJean-Christophe PLAGNIOL-VILLARD #endif /* CFG_FLASH_USE_BUFFER_WRITE */ 112659829cc1SJean-Christophe PLAGNIOL-VILLARD if (cnt == 0) { 112759829cc1SJean-Christophe PLAGNIOL-VILLARD return (0); 112859829cc1SJean-Christophe PLAGNIOL-VILLARD } 112959829cc1SJean-Christophe PLAGNIOL-VILLARD 113059829cc1SJean-Christophe PLAGNIOL-VILLARD /* 113159829cc1SJean-Christophe PLAGNIOL-VILLARD * handle unaligned tail bytes 113259829cc1SJean-Christophe PLAGNIOL-VILLARD */ 113359829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 113459829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) { 113559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 113659829cc1SJean-Christophe PLAGNIOL-VILLARD --cnt; 113759829cc1SJean-Christophe PLAGNIOL-VILLARD } 113859829cc1SJean-Christophe PLAGNIOL-VILLARD for (; i < info->portwidth; ++i, ++cp) { 113959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, (*(uchar *) cp)); 114059829cc1SJean-Christophe PLAGNIOL-VILLARD } 114159829cc1SJean-Christophe PLAGNIOL-VILLARD 114259829cc1SJean-Christophe PLAGNIOL-VILLARD return flash_write_cfiword (info, wp, cword); 114359829cc1SJean-Christophe PLAGNIOL-VILLARD } 114459829cc1SJean-Christophe PLAGNIOL-VILLARD 114559829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 114659829cc1SJean-Christophe PLAGNIOL-VILLARD */ 114759829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_PROTECTION 114859829cc1SJean-Christophe PLAGNIOL-VILLARD 114959829cc1SJean-Christophe PLAGNIOL-VILLARD int flash_real_protect (flash_info_t * info, long sector, int prot) 115059829cc1SJean-Christophe PLAGNIOL-VILLARD { 115159829cc1SJean-Christophe PLAGNIOL-VILLARD int retcode = 0; 115259829cc1SJean-Christophe PLAGNIOL-VILLARD 115359829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); 115459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT); 115559829cc1SJean-Christophe PLAGNIOL-VILLARD if (prot) 115659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET); 115759829cc1SJean-Christophe PLAGNIOL-VILLARD else 115859829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR); 115959829cc1SJean-Christophe PLAGNIOL-VILLARD 116059829cc1SJean-Christophe PLAGNIOL-VILLARD if ((retcode = 116159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_full_status_check (info, sector, info->erase_blk_tout, 116259829cc1SJean-Christophe PLAGNIOL-VILLARD prot ? "protect" : "unprotect")) == 0) { 116359829cc1SJean-Christophe PLAGNIOL-VILLARD 116459829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[sector] = prot; 116559829cc1SJean-Christophe PLAGNIOL-VILLARD 116659829cc1SJean-Christophe PLAGNIOL-VILLARD /* 116759829cc1SJean-Christophe PLAGNIOL-VILLARD * On some of Intel's flash chips (marked via legacy_unlock) 116859829cc1SJean-Christophe PLAGNIOL-VILLARD * unprotect unprotects all locking. 116959829cc1SJean-Christophe PLAGNIOL-VILLARD */ 117059829cc1SJean-Christophe PLAGNIOL-VILLARD if ((prot == 0) && (info->legacy_unlock)) { 117159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_sect_t i; 117259829cc1SJean-Christophe PLAGNIOL-VILLARD 117359829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->sector_count; i++) { 117459829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->protect[i]) 117559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_real_protect (info, i, 1); 117659829cc1SJean-Christophe PLAGNIOL-VILLARD } 117759829cc1SJean-Christophe PLAGNIOL-VILLARD } 117859829cc1SJean-Christophe PLAGNIOL-VILLARD } 117959829cc1SJean-Christophe PLAGNIOL-VILLARD return retcode; 118059829cc1SJean-Christophe PLAGNIOL-VILLARD } 118159829cc1SJean-Christophe PLAGNIOL-VILLARD 118259829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 118359829cc1SJean-Christophe PLAGNIOL-VILLARD * flash_read_user_serial - read the OneTimeProgramming cells 118459829cc1SJean-Christophe PLAGNIOL-VILLARD */ 118559829cc1SJean-Christophe PLAGNIOL-VILLARD void flash_read_user_serial (flash_info_t * info, void *buffer, int offset, 118659829cc1SJean-Christophe PLAGNIOL-VILLARD int len) 118759829cc1SJean-Christophe PLAGNIOL-VILLARD { 118859829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *src; 118959829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *dst; 119059829cc1SJean-Christophe PLAGNIOL-VILLARD 119159829cc1SJean-Christophe PLAGNIOL-VILLARD dst = buffer; 119259829cc1SJean-Christophe PLAGNIOL-VILLARD src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION); 119359829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID); 119459829cc1SJean-Christophe PLAGNIOL-VILLARD memcpy (dst, src + offset, len); 119559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 119659829cc1SJean-Christophe PLAGNIOL-VILLARD } 119759829cc1SJean-Christophe PLAGNIOL-VILLARD 119859829cc1SJean-Christophe PLAGNIOL-VILLARD /* 119959829cc1SJean-Christophe PLAGNIOL-VILLARD * flash_read_factory_serial - read the device Id from the protection area 120059829cc1SJean-Christophe PLAGNIOL-VILLARD */ 120159829cc1SJean-Christophe PLAGNIOL-VILLARD void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset, 120259829cc1SJean-Christophe PLAGNIOL-VILLARD int len) 120359829cc1SJean-Christophe PLAGNIOL-VILLARD { 120459829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *src; 120559829cc1SJean-Christophe PLAGNIOL-VILLARD 120659829cc1SJean-Christophe PLAGNIOL-VILLARD src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION); 120759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID); 120859829cc1SJean-Christophe PLAGNIOL-VILLARD memcpy (buffer, src + offset, len); 120959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 121059829cc1SJean-Christophe PLAGNIOL-VILLARD } 121159829cc1SJean-Christophe PLAGNIOL-VILLARD 121259829cc1SJean-Christophe PLAGNIOL-VILLARD #endif /* CFG_FLASH_PROTECTION */ 121359829cc1SJean-Christophe PLAGNIOL-VILLARD 121459829cc1SJean-Christophe PLAGNIOL-VILLARD 121559829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 121659829cc1SJean-Christophe PLAGNIOL-VILLARD * read jedec ids from device and set corresponding fields in info struct 121759829cc1SJean-Christophe PLAGNIOL-VILLARD * 121859829cc1SJean-Christophe PLAGNIOL-VILLARD * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct 121959829cc1SJean-Christophe PLAGNIOL-VILLARD * 122059829cc1SJean-Christophe PLAGNIOL-VILLARD */ 122159829cc1SJean-Christophe PLAGNIOL-VILLARD static void flash_read_jedec_ids (flash_info_t * info) 122259829cc1SJean-Christophe PLAGNIOL-VILLARD { 122359829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id = 0; 122459829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id = 0; 122559829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 = 0; 122659829cc1SJean-Christophe PLAGNIOL-VILLARD 122759829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 122859829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 122959829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 123059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); 123159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID); 123259829cc1SJean-Christophe PLAGNIOL-VILLARD udelay(1000); /* some flash are slow to respond */ 123359829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id = flash_read_uchar (info, 123459829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_MANUFACTURER_ID); 123559829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id = flash_read_uchar (info, 123659829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID); 123759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); 123859829cc1SJean-Christophe PLAGNIOL-VILLARD break; 123959829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 124059829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 124159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, AMD_CMD_RESET); 124259829cc1SJean-Christophe PLAGNIOL-VILLARD flash_unlock_seq(info, 0); 124381b20cccSMichael Schwingen flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID); 124459829cc1SJean-Christophe PLAGNIOL-VILLARD udelay(1000); /* some flash are slow to respond */ 124559829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id = flash_read_uchar (info, 124659829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_MANUFACTURER_ID); 124759829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id = flash_read_uchar (info, 124859829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID); 124959829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->device_id == 0x7E) { 125059829cc1SJean-Christophe PLAGNIOL-VILLARD /* AMD 3-byte (expanded) device ids */ 125159829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 = flash_read_uchar (info, 125259829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID2); 125359829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 <<= 8; 125459829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 |= flash_read_uchar (info, 125559829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID3); 125659829cc1SJean-Christophe PLAGNIOL-VILLARD } 125759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, AMD_CMD_RESET); 125859829cc1SJean-Christophe PLAGNIOL-VILLARD break; 125959829cc1SJean-Christophe PLAGNIOL-VILLARD default: 126059829cc1SJean-Christophe PLAGNIOL-VILLARD break; 126159829cc1SJean-Christophe PLAGNIOL-VILLARD } 126259829cc1SJean-Christophe PLAGNIOL-VILLARD } 126359829cc1SJean-Christophe PLAGNIOL-VILLARD 1264*be60a902SHaavard Skinnemoen #ifdef CONFIG_FLASH_CFI_LEGACY 1265*be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 1266*be60a902SHaavard Skinnemoen * Call board code to request info about non-CFI flash. 1267*be60a902SHaavard Skinnemoen * board_flash_get_legacy needs to fill in at least: 1268*be60a902SHaavard Skinnemoen * info->portwidth, info->chipwidth and info->interface for Jedec probing. 1269*be60a902SHaavard Skinnemoen */ 1270*be60a902SHaavard Skinnemoen static int flash_detect_legacy(ulong base, int banknum) 1271*be60a902SHaavard Skinnemoen { 1272*be60a902SHaavard Skinnemoen flash_info_t *info = &flash_info[banknum]; 1273*be60a902SHaavard Skinnemoen 1274*be60a902SHaavard Skinnemoen if (board_flash_get_legacy(base, banknum, info)) { 1275*be60a902SHaavard Skinnemoen /* board code may have filled info completely. If not, we 1276*be60a902SHaavard Skinnemoen use JEDEC ID probing. */ 1277*be60a902SHaavard Skinnemoen if (!info->vendor) { 1278*be60a902SHaavard Skinnemoen int modes[] = { 1279*be60a902SHaavard Skinnemoen CFI_CMDSET_AMD_STANDARD, 1280*be60a902SHaavard Skinnemoen CFI_CMDSET_INTEL_STANDARD 1281*be60a902SHaavard Skinnemoen }; 1282*be60a902SHaavard Skinnemoen int i; 1283*be60a902SHaavard Skinnemoen 1284*be60a902SHaavard Skinnemoen for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) { 1285*be60a902SHaavard Skinnemoen info->vendor = modes[i]; 1286*be60a902SHaavard Skinnemoen info->start[0] = base; 1287*be60a902SHaavard Skinnemoen if (info->portwidth == FLASH_CFI_8BIT 1288*be60a902SHaavard Skinnemoen && info->interface == FLASH_CFI_X8X16) { 1289*be60a902SHaavard Skinnemoen info->addr_unlock1 = 0x2AAA; 1290*be60a902SHaavard Skinnemoen info->addr_unlock2 = 0x5555; 1291*be60a902SHaavard Skinnemoen } else { 1292*be60a902SHaavard Skinnemoen info->addr_unlock1 = 0x5555; 1293*be60a902SHaavard Skinnemoen info->addr_unlock2 = 0x2AAA; 1294*be60a902SHaavard Skinnemoen } 1295*be60a902SHaavard Skinnemoen flash_read_jedec_ids(info); 1296*be60a902SHaavard Skinnemoen debug("JEDEC PROBE: ID %x %x %x\n", 1297*be60a902SHaavard Skinnemoen info->manufacturer_id, 1298*be60a902SHaavard Skinnemoen info->device_id, 1299*be60a902SHaavard Skinnemoen info->device_id2); 1300*be60a902SHaavard Skinnemoen if (jedec_flash_match(info, base)) 1301*be60a902SHaavard Skinnemoen break; 1302*be60a902SHaavard Skinnemoen } 1303*be60a902SHaavard Skinnemoen } 1304*be60a902SHaavard Skinnemoen 1305*be60a902SHaavard Skinnemoen switch(info->vendor) { 1306*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 1307*be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 1308*be60a902SHaavard Skinnemoen info->cmd_reset = FLASH_CMD_RESET; 1309*be60a902SHaavard Skinnemoen break; 1310*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_STANDARD: 1311*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_EXTENDED: 1312*be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_LEGACY: 1313*be60a902SHaavard Skinnemoen info->cmd_reset = AMD_CMD_RESET; 1314*be60a902SHaavard Skinnemoen break; 1315*be60a902SHaavard Skinnemoen } 1316*be60a902SHaavard Skinnemoen info->flash_id = FLASH_MAN_CFI; 1317*be60a902SHaavard Skinnemoen return 1; 1318*be60a902SHaavard Skinnemoen } 1319*be60a902SHaavard Skinnemoen return 0; /* use CFI */ 1320*be60a902SHaavard Skinnemoen } 1321*be60a902SHaavard Skinnemoen #else 1322*be60a902SHaavard Skinnemoen static inline int flash_detect_legacy(ulong base, int banknum) 1323*be60a902SHaavard Skinnemoen { 1324*be60a902SHaavard Skinnemoen return 0; /* use CFI */ 1325*be60a902SHaavard Skinnemoen } 1326*be60a902SHaavard Skinnemoen #endif 1327*be60a902SHaavard Skinnemoen 132859829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 132959829cc1SJean-Christophe PLAGNIOL-VILLARD * detect if flash is compatible with the Common Flash Interface (CFI) 133059829cc1SJean-Christophe PLAGNIOL-VILLARD * http://www.jedec.org/download/search/jesd68.pdf 133159829cc1SJean-Christophe PLAGNIOL-VILLARD */ 13327e5b9b47SHaavard Skinnemoen static int __flash_detect_cfi (flash_info_t * info) 133359829cc1SJean-Christophe PLAGNIOL-VILLARD { 133459829cc1SJean-Christophe PLAGNIOL-VILLARD int cfi_offset; 133559829cc1SJean-Christophe PLAGNIOL-VILLARD 133659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 13377e5b9b47SHaavard Skinnemoen for (cfi_offset=0; 13387e5b9b47SHaavard Skinnemoen cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint); 13397e5b9b47SHaavard Skinnemoen cfi_offset++) { 13407e5b9b47SHaavard Skinnemoen flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], 13417e5b9b47SHaavard Skinnemoen FLASH_CMD_CFI); 134259829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') 134359829cc1SJean-Christophe PLAGNIOL-VILLARD && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') 134459829cc1SJean-Christophe PLAGNIOL-VILLARD && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { 13457e5b9b47SHaavard Skinnemoen info->interface = flash_read_ushort (info, 0, 13467e5b9b47SHaavard Skinnemoen FLASH_OFFSET_INTERFACE); 134759829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_offset = flash_offset_cfi[cfi_offset]; 134859829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("device interface is %d\n", 134959829cc1SJean-Christophe PLAGNIOL-VILLARD info->interface); 135059829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("found port %d chip %d ", 135159829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth, info->chipwidth); 135259829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("port %d bits chip %d bits\n", 135359829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth << CFI_FLASH_SHIFT_WIDTH, 135459829cc1SJean-Christophe PLAGNIOL-VILLARD info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 135542026c9cSBartlomiej Sieka 135642026c9cSBartlomiej Sieka /* calculate command offsets as in the Linux driver */ 135742026c9cSBartlomiej Sieka info->addr_unlock1 = 0x555; 135842026c9cSBartlomiej Sieka info->addr_unlock2 = 0x2aa; 135942026c9cSBartlomiej Sieka 136042026c9cSBartlomiej Sieka /* 136142026c9cSBartlomiej Sieka * modify the unlock address if we are 136242026c9cSBartlomiej Sieka * in compatibility mode 136342026c9cSBartlomiej Sieka */ 136442026c9cSBartlomiej Sieka if ( /* x8/x16 in x8 mode */ 136542026c9cSBartlomiej Sieka ((info->chipwidth == FLASH_CFI_BY8) && 136642026c9cSBartlomiej Sieka (info->interface == FLASH_CFI_X8X16)) || 136742026c9cSBartlomiej Sieka /* x16/x32 in x16 mode */ 136842026c9cSBartlomiej Sieka ((info->chipwidth == FLASH_CFI_BY16) && 136942026c9cSBartlomiej Sieka (info->interface == FLASH_CFI_X16X32))) 137042026c9cSBartlomiej Sieka { 137142026c9cSBartlomiej Sieka info->addr_unlock1 = 0xaaa; 137242026c9cSBartlomiej Sieka info->addr_unlock2 = 0x555; 137342026c9cSBartlomiej Sieka } 137442026c9cSBartlomiej Sieka 137581b20cccSMichael Schwingen info->name = "CFI conformant"; 137659829cc1SJean-Christophe PLAGNIOL-VILLARD return 1; 137759829cc1SJean-Christophe PLAGNIOL-VILLARD } 137859829cc1SJean-Christophe PLAGNIOL-VILLARD } 13797e5b9b47SHaavard Skinnemoen 13807e5b9b47SHaavard Skinnemoen return 0; 138159829cc1SJean-Christophe PLAGNIOL-VILLARD } 13827e5b9b47SHaavard Skinnemoen 13837e5b9b47SHaavard Skinnemoen static int flash_detect_cfi (flash_info_t * info) 13847e5b9b47SHaavard Skinnemoen { 13857e5b9b47SHaavard Skinnemoen debug ("flash detect cfi\n"); 13867e5b9b47SHaavard Skinnemoen 13877e5b9b47SHaavard Skinnemoen for (info->portwidth = CFG_FLASH_CFI_WIDTH; 13887e5b9b47SHaavard Skinnemoen info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) { 13897e5b9b47SHaavard Skinnemoen for (info->chipwidth = FLASH_CFI_BY8; 13907e5b9b47SHaavard Skinnemoen info->chipwidth <= info->portwidth; 13917e5b9b47SHaavard Skinnemoen info->chipwidth <<= 1) 13927e5b9b47SHaavard Skinnemoen if (__flash_detect_cfi(info)) 13937e5b9b47SHaavard Skinnemoen return 1; 139459829cc1SJean-Christophe PLAGNIOL-VILLARD } 139559829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("not found\n"); 139659829cc1SJean-Christophe PLAGNIOL-VILLARD return 0; 139759829cc1SJean-Christophe PLAGNIOL-VILLARD } 139859829cc1SJean-Christophe PLAGNIOL-VILLARD 139959829cc1SJean-Christophe PLAGNIOL-VILLARD /* 140059829cc1SJean-Christophe PLAGNIOL-VILLARD * The following code cannot be run from FLASH! 140159829cc1SJean-Christophe PLAGNIOL-VILLARD * 140259829cc1SJean-Christophe PLAGNIOL-VILLARD */ 140359829cc1SJean-Christophe PLAGNIOL-VILLARD ulong flash_get_size (ulong base, int banknum) 140459829cc1SJean-Christophe PLAGNIOL-VILLARD { 140559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_info_t *info = &flash_info[banknum]; 140659829cc1SJean-Christophe PLAGNIOL-VILLARD int i, j; 140759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_sect_t sect_cnt; 140859829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned long sector; 140959829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned long tmp; 141059829cc1SJean-Christophe PLAGNIOL-VILLARD int size_ratio; 141159829cc1SJean-Christophe PLAGNIOL-VILLARD uchar num_erase_regions; 141259829cc1SJean-Christophe PLAGNIOL-VILLARD int erase_region_size; 141359829cc1SJean-Christophe PLAGNIOL-VILLARD int erase_region_count; 141459829cc1SJean-Christophe PLAGNIOL-VILLARD int geometry_reversed = 0; 141559829cc1SJean-Christophe PLAGNIOL-VILLARD 141659829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr = 0; 141759829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_version = 0; 141859829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_PROTECTION 141959829cc1SJean-Christophe PLAGNIOL-VILLARD info->legacy_unlock = 0; 142059829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 142159829cc1SJean-Christophe PLAGNIOL-VILLARD 142259829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[0] = base; 142359829cc1SJean-Christophe PLAGNIOL-VILLARD 142459829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_detect_cfi (info)) { 142559829cc1SJean-Christophe PLAGNIOL-VILLARD info->vendor = flash_read_ushort (info, 0, 142659829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_PRIMARY_VENDOR); 142759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_read_jedec_ids (info); 142859829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI); 142959829cc1SJean-Christophe PLAGNIOL-VILLARD num_erase_regions = flash_read_uchar (info, 143059829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_NUM_ERASE_REGIONS); 143159829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr = flash_read_ushort (info, 0, 143259829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_EXT_QUERY_T_P_ADDR); 143359829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->ext_addr) { 143459829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_version = (ushort) flash_read_uchar (info, 143559829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr + 3) << 8; 143659829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_version |= (ushort) flash_read_uchar (info, 143759829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr + 4); 143859829cc1SJean-Christophe PLAGNIOL-VILLARD } 143959829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 144059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_printqry (info, 0); 144159829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 144259829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 144359829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 144459829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 144559829cc1SJean-Christophe PLAGNIOL-VILLARD default: 144659829cc1SJean-Christophe PLAGNIOL-VILLARD info->cmd_reset = FLASH_CMD_RESET; 144759829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_PROTECTION 144859829cc1SJean-Christophe PLAGNIOL-VILLARD /* read legacy lock/unlock bit from intel flash */ 144959829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->ext_addr) { 145059829cc1SJean-Christophe PLAGNIOL-VILLARD info->legacy_unlock = flash_read_uchar (info, 145159829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr + 5) & 0x08; 145259829cc1SJean-Christophe PLAGNIOL-VILLARD } 145359829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 145459829cc1SJean-Christophe PLAGNIOL-VILLARD break; 145559829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 145659829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 145759829cc1SJean-Christophe PLAGNIOL-VILLARD info->cmd_reset = AMD_CMD_RESET; 145859829cc1SJean-Christophe PLAGNIOL-VILLARD /* check if flash geometry needs reversal */ 145959829cc1SJean-Christophe PLAGNIOL-VILLARD if (num_erase_regions <= 1) 146059829cc1SJean-Christophe PLAGNIOL-VILLARD break; 146159829cc1SJean-Christophe PLAGNIOL-VILLARD /* reverse geometry if top boot part */ 146259829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->cfi_version < 0x3131) { 146359829cc1SJean-Christophe PLAGNIOL-VILLARD /* CFI < 1.1, try to guess from device id */ 146459829cc1SJean-Christophe PLAGNIOL-VILLARD if ((info->device_id & 0x80) != 0) { 146559829cc1SJean-Christophe PLAGNIOL-VILLARD geometry_reversed = 1; 146659829cc1SJean-Christophe PLAGNIOL-VILLARD } 146759829cc1SJean-Christophe PLAGNIOL-VILLARD break; 146859829cc1SJean-Christophe PLAGNIOL-VILLARD } 146959829cc1SJean-Christophe PLAGNIOL-VILLARD /* CFI >= 1.1, deduct from top/bottom flag */ 147059829cc1SJean-Christophe PLAGNIOL-VILLARD /* note: ext_addr is valid since cfi_version > 0 */ 147159829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) { 147259829cc1SJean-Christophe PLAGNIOL-VILLARD geometry_reversed = 1; 147359829cc1SJean-Christophe PLAGNIOL-VILLARD } 147459829cc1SJean-Christophe PLAGNIOL-VILLARD break; 147559829cc1SJean-Christophe PLAGNIOL-VILLARD } 147659829cc1SJean-Christophe PLAGNIOL-VILLARD 147759829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("manufacturer is %d\n", info->vendor); 147859829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("manufacturer id is 0x%x\n", info->manufacturer_id); 147959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("device id is 0x%x\n", info->device_id); 148059829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("device id2 is 0x%x\n", info->device_id2); 148159829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("cfi version is 0x%04x\n", info->cfi_version); 148259829cc1SJean-Christophe PLAGNIOL-VILLARD 148359829cc1SJean-Christophe PLAGNIOL-VILLARD size_ratio = info->portwidth / info->chipwidth; 148459829cc1SJean-Christophe PLAGNIOL-VILLARD /* if the chip is x8/x16 reduce the ratio by half */ 148559829cc1SJean-Christophe PLAGNIOL-VILLARD if ((info->interface == FLASH_CFI_X8X16) 148659829cc1SJean-Christophe PLAGNIOL-VILLARD && (info->chipwidth == FLASH_CFI_BY8)) { 148759829cc1SJean-Christophe PLAGNIOL-VILLARD size_ratio >>= 1; 148859829cc1SJean-Christophe PLAGNIOL-VILLARD } 148959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("size_ratio %d port %d bits chip %d bits\n", 149059829cc1SJean-Christophe PLAGNIOL-VILLARD size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH, 149159829cc1SJean-Christophe PLAGNIOL-VILLARD info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 149259829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("found %d erase regions\n", num_erase_regions); 149359829cc1SJean-Christophe PLAGNIOL-VILLARD sect_cnt = 0; 149459829cc1SJean-Christophe PLAGNIOL-VILLARD sector = base; 149559829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < num_erase_regions; i++) { 149659829cc1SJean-Christophe PLAGNIOL-VILLARD if (i > NUM_ERASE_REGIONS) { 149759829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("%d erase regions found, only %d used\n", 149859829cc1SJean-Christophe PLAGNIOL-VILLARD num_erase_regions, NUM_ERASE_REGIONS); 149959829cc1SJean-Christophe PLAGNIOL-VILLARD break; 150059829cc1SJean-Christophe PLAGNIOL-VILLARD } 150159829cc1SJean-Christophe PLAGNIOL-VILLARD if (geometry_reversed) 150259829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = flash_read_long (info, 0, 150359829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_ERASE_REGIONS + 150459829cc1SJean-Christophe PLAGNIOL-VILLARD (num_erase_regions - 1 - i) * 4); 150559829cc1SJean-Christophe PLAGNIOL-VILLARD else 150659829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = flash_read_long (info, 0, 150759829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_ERASE_REGIONS + 150859829cc1SJean-Christophe PLAGNIOL-VILLARD i * 4); 150959829cc1SJean-Christophe PLAGNIOL-VILLARD erase_region_size = 151059829cc1SJean-Christophe PLAGNIOL-VILLARD (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128; 151159829cc1SJean-Christophe PLAGNIOL-VILLARD tmp >>= 16; 151259829cc1SJean-Christophe PLAGNIOL-VILLARD erase_region_count = (tmp & 0xffff) + 1; 151359829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("erase_region_count = %d erase_region_size = %d\n", 151459829cc1SJean-Christophe PLAGNIOL-VILLARD erase_region_count, erase_region_size); 151559829cc1SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < erase_region_count; j++) { 151681b20cccSMichael Schwingen if (sect_cnt >= CFG_MAX_FLASH_SECT) { 151781b20cccSMichael Schwingen printf("ERROR: too many flash sectors\n"); 151881b20cccSMichael Schwingen break; 151981b20cccSMichael Schwingen } 152059829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[sect_cnt] = sector; 152159829cc1SJean-Christophe PLAGNIOL-VILLARD sector += (erase_region_size * size_ratio); 152259829cc1SJean-Christophe PLAGNIOL-VILLARD 152359829cc1SJean-Christophe PLAGNIOL-VILLARD /* 15247e5b9b47SHaavard Skinnemoen * Only read protection status from 15257e5b9b47SHaavard Skinnemoen * supported devices (intel...) 152659829cc1SJean-Christophe PLAGNIOL-VILLARD */ 152759829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 152859829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 152959829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 153059829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[sect_cnt] = 153159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_isset (info, sect_cnt, 153259829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_PROTECT, 153359829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_STATUS_PROTECT); 153459829cc1SJean-Christophe PLAGNIOL-VILLARD break; 153559829cc1SJean-Christophe PLAGNIOL-VILLARD default: 15367e5b9b47SHaavard Skinnemoen /* default: not protected */ 15377e5b9b47SHaavard Skinnemoen info->protect[sect_cnt] = 0; 153859829cc1SJean-Christophe PLAGNIOL-VILLARD } 153959829cc1SJean-Christophe PLAGNIOL-VILLARD 154059829cc1SJean-Christophe PLAGNIOL-VILLARD sect_cnt++; 154159829cc1SJean-Christophe PLAGNIOL-VILLARD } 154259829cc1SJean-Christophe PLAGNIOL-VILLARD } 154359829cc1SJean-Christophe PLAGNIOL-VILLARD 154459829cc1SJean-Christophe PLAGNIOL-VILLARD info->sector_count = sect_cnt; 15457e5b9b47SHaavard Skinnemoen info->size = 1 << flash_read_uchar (info, FLASH_OFFSET_SIZE); 154659829cc1SJean-Christophe PLAGNIOL-VILLARD /* multiply the size by the number of chips */ 15477e5b9b47SHaavard Skinnemoen info->size *= size_ratio; 15487e5b9b47SHaavard Skinnemoen info->buffer_size = 1 << flash_read_ushort (info, 0, 15497e5b9b47SHaavard Skinnemoen FLASH_OFFSET_BUFFER_SIZE); 155059829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT); 15517e5b9b47SHaavard Skinnemoen info->erase_blk_tout = tmp * 15527e5b9b47SHaavard Skinnemoen (1 << flash_read_uchar ( 15537e5b9b47SHaavard Skinnemoen info, FLASH_OFFSET_EMAX_TOUT)); 155459829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT)) * 155559829cc1SJean-Christophe PLAGNIOL-VILLARD (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)); 15567e5b9b47SHaavard Skinnemoen /* round up when converting to ms */ 15577e5b9b47SHaavard Skinnemoen info->buffer_write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); 155859829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) * 155959829cc1SJean-Christophe PLAGNIOL-VILLARD (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT)); 15607e5b9b47SHaavard Skinnemoen /* round up when converting to ms */ 15617e5b9b47SHaavard Skinnemoen info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); 156259829cc1SJean-Christophe PLAGNIOL-VILLARD info->flash_id = FLASH_MAN_CFI; 15637e5b9b47SHaavard Skinnemoen if ((info->interface == FLASH_CFI_X8X16) && 15647e5b9b47SHaavard Skinnemoen (info->chipwidth == FLASH_CFI_BY8)) { 15657e5b9b47SHaavard Skinnemoen /* XXX - Need to test on x8/x16 in parallel. */ 15667e5b9b47SHaavard Skinnemoen info->portwidth >>= 1; 156759829cc1SJean-Christophe PLAGNIOL-VILLARD } 156859829cc1SJean-Christophe PLAGNIOL-VILLARD } 156959829cc1SJean-Christophe PLAGNIOL-VILLARD 157059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 157159829cc1SJean-Christophe PLAGNIOL-VILLARD return (info->size); 157259829cc1SJean-Christophe PLAGNIOL-VILLARD } 157359829cc1SJean-Christophe PLAGNIOL-VILLARD 157459829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 157559829cc1SJean-Christophe PLAGNIOL-VILLARD */ 1576*be60a902SHaavard Skinnemoen unsigned long flash_init (void) 157759829cc1SJean-Christophe PLAGNIOL-VILLARD { 1578*be60a902SHaavard Skinnemoen unsigned long size = 0; 1579*be60a902SHaavard Skinnemoen int i; 158059829cc1SJean-Christophe PLAGNIOL-VILLARD 1581*be60a902SHaavard Skinnemoen #ifdef CFG_FLASH_PROTECTION 1582*be60a902SHaavard Skinnemoen char *s = getenv("unlock"); 158381b20cccSMichael Schwingen #endif 1584*be60a902SHaavard Skinnemoen 1585*be60a902SHaavard Skinnemoen /* Init: no FLASHes known */ 1586*be60a902SHaavard Skinnemoen for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { 1587*be60a902SHaavard Skinnemoen flash_info[i].flash_id = FLASH_UNKNOWN; 1588*be60a902SHaavard Skinnemoen 1589*be60a902SHaavard Skinnemoen if (!flash_detect_legacy (bank_base[i], i)) 1590*be60a902SHaavard Skinnemoen flash_get_size (bank_base[i], i); 1591*be60a902SHaavard Skinnemoen size += flash_info[i].size; 1592*be60a902SHaavard Skinnemoen if (flash_info[i].flash_id == FLASH_UNKNOWN) { 1593*be60a902SHaavard Skinnemoen #ifndef CFG_FLASH_QUIET_TEST 1594*be60a902SHaavard Skinnemoen printf ("## Unknown FLASH on Bank %d " 1595*be60a902SHaavard Skinnemoen "- Size = 0x%08lx = %ld MB\n", 1596*be60a902SHaavard Skinnemoen i+1, flash_info[i].size, 1597*be60a902SHaavard Skinnemoen flash_info[i].size << 20); 1598*be60a902SHaavard Skinnemoen #endif /* CFG_FLASH_QUIET_TEST */ 159959829cc1SJean-Christophe PLAGNIOL-VILLARD } 1600*be60a902SHaavard Skinnemoen #ifdef CFG_FLASH_PROTECTION 1601*be60a902SHaavard Skinnemoen else if ((s != NULL) && (strcmp(s, "yes") == 0)) { 1602*be60a902SHaavard Skinnemoen /* 1603*be60a902SHaavard Skinnemoen * Only the U-Boot image and it's environment 1604*be60a902SHaavard Skinnemoen * is protected, all other sectors are 1605*be60a902SHaavard Skinnemoen * unprotected (unlocked) if flash hardware 1606*be60a902SHaavard Skinnemoen * protection is used (CFG_FLASH_PROTECTION) 1607*be60a902SHaavard Skinnemoen * and the environment variable "unlock" is 1608*be60a902SHaavard Skinnemoen * set to "yes". 1609*be60a902SHaavard Skinnemoen */ 1610*be60a902SHaavard Skinnemoen if (flash_info[i].legacy_unlock) { 1611*be60a902SHaavard Skinnemoen int k; 161259829cc1SJean-Christophe PLAGNIOL-VILLARD 1613*be60a902SHaavard Skinnemoen /* 1614*be60a902SHaavard Skinnemoen * Disable legacy_unlock temporarily, 1615*be60a902SHaavard Skinnemoen * since flash_real_protect would 1616*be60a902SHaavard Skinnemoen * relock all other sectors again 1617*be60a902SHaavard Skinnemoen * otherwise. 1618*be60a902SHaavard Skinnemoen */ 1619*be60a902SHaavard Skinnemoen flash_info[i].legacy_unlock = 0; 162059829cc1SJean-Christophe PLAGNIOL-VILLARD 1621*be60a902SHaavard Skinnemoen /* 1622*be60a902SHaavard Skinnemoen * Legacy unlocking (e.g. Intel J3) -> 1623*be60a902SHaavard Skinnemoen * unlock only one sector. This will 1624*be60a902SHaavard Skinnemoen * unlock all sectors. 1625*be60a902SHaavard Skinnemoen */ 1626*be60a902SHaavard Skinnemoen flash_real_protect (&flash_info[i], 0, 0); 162759829cc1SJean-Christophe PLAGNIOL-VILLARD 1628*be60a902SHaavard Skinnemoen flash_info[i].legacy_unlock = 1; 162959829cc1SJean-Christophe PLAGNIOL-VILLARD 1630*be60a902SHaavard Skinnemoen /* 1631*be60a902SHaavard Skinnemoen * Manually mark other sectors as 1632*be60a902SHaavard Skinnemoen * unlocked (unprotected) 1633*be60a902SHaavard Skinnemoen */ 1634*be60a902SHaavard Skinnemoen for (k = 1; k < flash_info[i].sector_count; k++) 1635*be60a902SHaavard Skinnemoen flash_info[i].protect[k] = 0; 1636*be60a902SHaavard Skinnemoen } else { 1637*be60a902SHaavard Skinnemoen /* 1638*be60a902SHaavard Skinnemoen * No legancy unlocking -> unlock all sectors 1639*be60a902SHaavard Skinnemoen */ 1640*be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_CLEAR, 1641*be60a902SHaavard Skinnemoen flash_info[i].start[0], 1642*be60a902SHaavard Skinnemoen flash_info[i].start[0] 1643*be60a902SHaavard Skinnemoen + flash_info[i].size - 1, 1644*be60a902SHaavard Skinnemoen &flash_info[i]); 164559829cc1SJean-Christophe PLAGNIOL-VILLARD } 164659829cc1SJean-Christophe PLAGNIOL-VILLARD } 1647*be60a902SHaavard Skinnemoen #endif /* CFG_FLASH_PROTECTION */ 164859829cc1SJean-Christophe PLAGNIOL-VILLARD } 164959829cc1SJean-Christophe PLAGNIOL-VILLARD 1650*be60a902SHaavard Skinnemoen /* Monitor protection ON by default */ 1651*be60a902SHaavard Skinnemoen #if (CFG_MONITOR_BASE >= CFG_FLASH_BASE) 1652*be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_SET, 1653*be60a902SHaavard Skinnemoen CFG_MONITOR_BASE, 1654*be60a902SHaavard Skinnemoen CFG_MONITOR_BASE + monitor_flash_len - 1, 1655*be60a902SHaavard Skinnemoen flash_get_info(CFG_MONITOR_BASE)); 1656*be60a902SHaavard Skinnemoen #endif 165759829cc1SJean-Christophe PLAGNIOL-VILLARD 1658*be60a902SHaavard Skinnemoen /* Environment protection ON by default */ 1659*be60a902SHaavard Skinnemoen #ifdef CFG_ENV_IS_IN_FLASH 1660*be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_SET, 1661*be60a902SHaavard Skinnemoen CFG_ENV_ADDR, 1662*be60a902SHaavard Skinnemoen CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, 1663*be60a902SHaavard Skinnemoen flash_get_info(CFG_ENV_ADDR)); 1664*be60a902SHaavard Skinnemoen #endif 1665*be60a902SHaavard Skinnemoen 1666*be60a902SHaavard Skinnemoen /* Redundant environment protection ON by default */ 1667*be60a902SHaavard Skinnemoen #ifdef CFG_ENV_ADDR_REDUND 1668*be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_SET, 1669*be60a902SHaavard Skinnemoen CFG_ENV_ADDR_REDUND, 1670*be60a902SHaavard Skinnemoen CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1, 1671*be60a902SHaavard Skinnemoen flash_get_info(CFG_ENV_ADDR_REDUND)); 1672*be60a902SHaavard Skinnemoen #endif 1673*be60a902SHaavard Skinnemoen return (size); 167459829cc1SJean-Christophe PLAGNIOL-VILLARD } 167559829cc1SJean-Christophe PLAGNIOL-VILLARD 167659829cc1SJean-Christophe PLAGNIOL-VILLARD #endif /* CFG_FLASH_CFI */ 1677