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 #define NUM_ERASE_REGIONS 4 /* max. number of erase regions */ 15359829cc1SJean-Christophe PLAGNIOL-VILLARD 15459829cc1SJean-Christophe PLAGNIOL-VILLARD static uint flash_offset_cfi[2] = { FLASH_OFFSET_CFI, FLASH_OFFSET_CFI_ALT }; 15559829cc1SJean-Christophe PLAGNIOL-VILLARD 15659829cc1SJean-Christophe PLAGNIOL-VILLARD /* use CFG_MAX_FLASH_BANKS_DETECT if defined */ 15759829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_MAX_FLASH_BANKS_DETECT 15859829cc1SJean-Christophe PLAGNIOL-VILLARD static ulong bank_base[CFG_MAX_FLASH_BANKS_DETECT] = CFG_FLASH_BANKS_LIST; 15959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_info_t flash_info[CFG_MAX_FLASH_BANKS_DETECT]; /* FLASH chips info */ 16059829cc1SJean-Christophe PLAGNIOL-VILLARD #else 16159829cc1SJean-Christophe PLAGNIOL-VILLARD static ulong bank_base[CFG_MAX_FLASH_BANKS] = CFG_FLASH_BANKS_LIST; 16259829cc1SJean-Christophe PLAGNIOL-VILLARD flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* FLASH chips info */ 16359829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 16459829cc1SJean-Christophe PLAGNIOL-VILLARD 16559829cc1SJean-Christophe PLAGNIOL-VILLARD /* 16659829cc1SJean-Christophe PLAGNIOL-VILLARD * Check if chip width is defined. If not, start detecting with 8bit. 16759829cc1SJean-Christophe PLAGNIOL-VILLARD */ 16859829cc1SJean-Christophe PLAGNIOL-VILLARD #ifndef CFG_FLASH_CFI_WIDTH 16959829cc1SJean-Christophe PLAGNIOL-VILLARD #define CFG_FLASH_CFI_WIDTH FLASH_CFI_8BIT 17059829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 17159829cc1SJean-Christophe PLAGNIOL-VILLARD 17259829cc1SJean-Christophe PLAGNIOL-VILLARD typedef unsigned long flash_sect_t; 17359829cc1SJean-Christophe PLAGNIOL-VILLARD 174*cdbaefb5SHaavard Skinnemoen static void flash_write8(u8 value, void *addr) 175*cdbaefb5SHaavard Skinnemoen { 176*cdbaefb5SHaavard Skinnemoen __raw_writeb(value, addr); 177*cdbaefb5SHaavard Skinnemoen } 178*cdbaefb5SHaavard Skinnemoen 179*cdbaefb5SHaavard Skinnemoen static void flash_write16(u16 value, void *addr) 180*cdbaefb5SHaavard Skinnemoen { 181*cdbaefb5SHaavard Skinnemoen __raw_writew(value, addr); 182*cdbaefb5SHaavard Skinnemoen } 183*cdbaefb5SHaavard Skinnemoen 184*cdbaefb5SHaavard Skinnemoen static void flash_write32(u32 value, void *addr) 185*cdbaefb5SHaavard Skinnemoen { 186*cdbaefb5SHaavard Skinnemoen __raw_writel(value, addr); 187*cdbaefb5SHaavard Skinnemoen } 188*cdbaefb5SHaavard Skinnemoen 189*cdbaefb5SHaavard Skinnemoen static void flash_write64(u64 value, void *addr) 190*cdbaefb5SHaavard Skinnemoen { 191*cdbaefb5SHaavard Skinnemoen /* No architectures currently implement __raw_writeq() */ 192*cdbaefb5SHaavard Skinnemoen *(volatile u64 *)addr = value; 193*cdbaefb5SHaavard Skinnemoen } 194*cdbaefb5SHaavard Skinnemoen 195*cdbaefb5SHaavard Skinnemoen static u8 flash_read8(void *addr) 196*cdbaefb5SHaavard Skinnemoen { 197*cdbaefb5SHaavard Skinnemoen return __raw_readb(addr); 198*cdbaefb5SHaavard Skinnemoen } 199*cdbaefb5SHaavard Skinnemoen 200*cdbaefb5SHaavard Skinnemoen static u16 flash_read16(void *addr) 201*cdbaefb5SHaavard Skinnemoen { 202*cdbaefb5SHaavard Skinnemoen return __raw_readw(addr); 203*cdbaefb5SHaavard Skinnemoen } 204*cdbaefb5SHaavard Skinnemoen 205*cdbaefb5SHaavard Skinnemoen static u32 flash_read32(void *addr) 206*cdbaefb5SHaavard Skinnemoen { 207*cdbaefb5SHaavard Skinnemoen return __raw_readl(addr); 208*cdbaefb5SHaavard Skinnemoen } 209*cdbaefb5SHaavard Skinnemoen 210*cdbaefb5SHaavard Skinnemoen static u64 flash_read64(void *addr) 211*cdbaefb5SHaavard Skinnemoen { 212*cdbaefb5SHaavard Skinnemoen /* No architectures currently implement __raw_readq() */ 213*cdbaefb5SHaavard Skinnemoen return *(volatile u64 *)addr; 214*cdbaefb5SHaavard Skinnemoen } 215*cdbaefb5SHaavard Skinnemoen 216be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 217be60a902SHaavard Skinnemoen */ 21859829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(CFG_ENV_IS_IN_FLASH) || defined(CFG_ENV_ADDR_REDUND) || (CFG_MONITOR_BASE >= CFG_FLASH_BASE) 219be60a902SHaavard Skinnemoen static flash_info_t *flash_get_info(ulong base) 220be60a902SHaavard Skinnemoen { 221be60a902SHaavard Skinnemoen int i; 222be60a902SHaavard Skinnemoen flash_info_t * info = 0; 223be60a902SHaavard Skinnemoen 224be60a902SHaavard Skinnemoen for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { 225be60a902SHaavard Skinnemoen info = & flash_info[i]; 226be60a902SHaavard Skinnemoen if (info->size && info->start[0] <= base && 227be60a902SHaavard Skinnemoen base <= info->start[0] + info->size - 1) 228be60a902SHaavard Skinnemoen break; 229be60a902SHaavard Skinnemoen } 230be60a902SHaavard Skinnemoen 231be60a902SHaavard Skinnemoen return i == CFG_MAX_FLASH_BANKS ? 0 : info; 232be60a902SHaavard Skinnemoen } 23359829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 23459829cc1SJean-Christophe PLAGNIOL-VILLARD 23559829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 23659829cc1SJean-Christophe PLAGNIOL-VILLARD * create an address based on the offset and the port width 23759829cc1SJean-Christophe PLAGNIOL-VILLARD */ 2383055793bSHaavard Skinnemoen static inline uchar * 2397e5b9b47SHaavard Skinnemoen flash_make_addr (flash_info_t * info, flash_sect_t sect, uint offset) 24059829cc1SJean-Christophe PLAGNIOL-VILLARD { 24159829cc1SJean-Christophe PLAGNIOL-VILLARD return ((uchar *) (info->start[sect] + (offset * info->portwidth))); 24259829cc1SJean-Christophe PLAGNIOL-VILLARD } 24359829cc1SJean-Christophe PLAGNIOL-VILLARD 244be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 245be60a902SHaavard Skinnemoen * make a proper sized command based on the port and chip widths 246be60a902SHaavard Skinnemoen */ 247be60a902SHaavard Skinnemoen static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf) 248be60a902SHaavard Skinnemoen { 249be60a902SHaavard Skinnemoen int i; 250be60a902SHaavard Skinnemoen uchar *cp = (uchar *) cmdbuf; 251be60a902SHaavard Skinnemoen 252be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 253be60a902SHaavard Skinnemoen for (i = info->portwidth; i > 0; i--) 254be60a902SHaavard Skinnemoen #else 255be60a902SHaavard Skinnemoen for (i = 1; i <= info->portwidth; i++) 256be60a902SHaavard Skinnemoen #endif 257be60a902SHaavard Skinnemoen *cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd; 258be60a902SHaavard Skinnemoen } 259be60a902SHaavard Skinnemoen 26059829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 26159829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 26259829cc1SJean-Christophe PLAGNIOL-VILLARD * Debug support 26359829cc1SJean-Christophe PLAGNIOL-VILLARD */ 2643055793bSHaavard Skinnemoen static void print_longlong (char *str, unsigned long long data) 26559829cc1SJean-Christophe PLAGNIOL-VILLARD { 26659829cc1SJean-Christophe PLAGNIOL-VILLARD int i; 26759829cc1SJean-Christophe PLAGNIOL-VILLARD char *cp; 26859829cc1SJean-Christophe PLAGNIOL-VILLARD 26959829cc1SJean-Christophe PLAGNIOL-VILLARD cp = (unsigned char *) &data; 27059829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < 8; i++) 27159829cc1SJean-Christophe PLAGNIOL-VILLARD sprintf (&str[i * 2], "%2.2x", *cp++); 27259829cc1SJean-Christophe PLAGNIOL-VILLARD } 273be60a902SHaavard Skinnemoen 27459829cc1SJean-Christophe PLAGNIOL-VILLARD static void flash_printqry (flash_info_t * info, flash_sect_t sect) 27559829cc1SJean-Christophe PLAGNIOL-VILLARD { 276*cdbaefb5SHaavard Skinnemoen void *addr; 27759829cc1SJean-Christophe PLAGNIOL-VILLARD int x, y; 27859829cc1SJean-Christophe PLAGNIOL-VILLARD 27959829cc1SJean-Christophe PLAGNIOL-VILLARD for (x = 0; x < 0x40; x += 16U / info->portwidth) { 280*cdbaefb5SHaavard Skinnemoen addr = flash_make_addr (info, sect, 28159829cc1SJean-Christophe PLAGNIOL-VILLARD x + FLASH_OFFSET_CFI_RESP); 282*cdbaefb5SHaavard Skinnemoen debug ("%p : ", addr); 28359829cc1SJean-Christophe PLAGNIOL-VILLARD for (y = 0; y < 16; y++) { 284*cdbaefb5SHaavard Skinnemoen debug ("%2.2x ", flash_read8(addr + y)); 28559829cc1SJean-Christophe PLAGNIOL-VILLARD } 28659829cc1SJean-Christophe PLAGNIOL-VILLARD debug (" "); 28759829cc1SJean-Christophe PLAGNIOL-VILLARD for (y = 0; y < 16; y++) { 288*cdbaefb5SHaavard Skinnemoen unsigned char c = flash_read8(addr + y); 289*cdbaefb5SHaavard Skinnemoen if (c >= 0x20 && c <= 0x7e) { 290*cdbaefb5SHaavard Skinnemoen debug ("%c", c); 29159829cc1SJean-Christophe PLAGNIOL-VILLARD } else { 29259829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("."); 29359829cc1SJean-Christophe PLAGNIOL-VILLARD } 29459829cc1SJean-Christophe PLAGNIOL-VILLARD } 29559829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("\n"); 29659829cc1SJean-Christophe PLAGNIOL-VILLARD } 29759829cc1SJean-Christophe PLAGNIOL-VILLARD } 29859829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 29959829cc1SJean-Christophe PLAGNIOL-VILLARD 30059829cc1SJean-Christophe PLAGNIOL-VILLARD 30159829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 30259829cc1SJean-Christophe PLAGNIOL-VILLARD * read a character at a port width address 30359829cc1SJean-Christophe PLAGNIOL-VILLARD */ 3043055793bSHaavard Skinnemoen static inline uchar flash_read_uchar (flash_info_t * info, uint offset) 30559829cc1SJean-Christophe PLAGNIOL-VILLARD { 30659829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *cp; 30759829cc1SJean-Christophe PLAGNIOL-VILLARD 30859829cc1SJean-Christophe PLAGNIOL-VILLARD cp = flash_make_addr (info, 0, offset); 30959829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 31059829cc1SJean-Christophe PLAGNIOL-VILLARD return (cp[0]); 31159829cc1SJean-Christophe PLAGNIOL-VILLARD #else 31259829cc1SJean-Christophe PLAGNIOL-VILLARD return (cp[info->portwidth - 1]); 31359829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 31459829cc1SJean-Christophe PLAGNIOL-VILLARD } 31559829cc1SJean-Christophe PLAGNIOL-VILLARD 31659829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 31759829cc1SJean-Christophe PLAGNIOL-VILLARD * read a short word by swapping for ppc format. 31859829cc1SJean-Christophe PLAGNIOL-VILLARD */ 3193055793bSHaavard Skinnemoen static ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, 3203055793bSHaavard Skinnemoen uint offset) 32159829cc1SJean-Christophe PLAGNIOL-VILLARD { 32259829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *addr; 32359829cc1SJean-Christophe PLAGNIOL-VILLARD ushort retval; 32459829cc1SJean-Christophe PLAGNIOL-VILLARD 32559829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 32659829cc1SJean-Christophe PLAGNIOL-VILLARD int x; 32759829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 32859829cc1SJean-Christophe PLAGNIOL-VILLARD addr = flash_make_addr (info, sect, offset); 32959829cc1SJean-Christophe PLAGNIOL-VILLARD 33059829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 33159829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("ushort addr is at %p info->portwidth = %d\n", addr, 33259829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth); 33359829cc1SJean-Christophe PLAGNIOL-VILLARD for (x = 0; x < 2 * info->portwidth; x++) { 33459829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("addr[%x] = 0x%x\n", x, addr[x]); 33559829cc1SJean-Christophe PLAGNIOL-VILLARD } 33659829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 33759829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 33859829cc1SJean-Christophe PLAGNIOL-VILLARD retval = ((addr[(info->portwidth)] << 8) | addr[0]); 33959829cc1SJean-Christophe PLAGNIOL-VILLARD #else 34059829cc1SJean-Christophe PLAGNIOL-VILLARD retval = ((addr[(2 * info->portwidth) - 1] << 8) | 34159829cc1SJean-Christophe PLAGNIOL-VILLARD addr[info->portwidth - 1]); 34259829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 34359829cc1SJean-Christophe PLAGNIOL-VILLARD 34459829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("retval = 0x%x\n", retval); 34559829cc1SJean-Christophe PLAGNIOL-VILLARD return retval; 34659829cc1SJean-Christophe PLAGNIOL-VILLARD } 34759829cc1SJean-Christophe PLAGNIOL-VILLARD 34859829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 34959829cc1SJean-Christophe PLAGNIOL-VILLARD * read a long word by picking the least significant byte of each maximum 35059829cc1SJean-Christophe PLAGNIOL-VILLARD * port size word. Swap for ppc format. 35159829cc1SJean-Christophe PLAGNIOL-VILLARD */ 3523055793bSHaavard Skinnemoen static ulong flash_read_long (flash_info_t * info, flash_sect_t sect, 3533055793bSHaavard Skinnemoen uint offset) 35459829cc1SJean-Christophe PLAGNIOL-VILLARD { 35559829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *addr; 35659829cc1SJean-Christophe PLAGNIOL-VILLARD ulong retval; 35759829cc1SJean-Christophe PLAGNIOL-VILLARD 35859829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 35959829cc1SJean-Christophe PLAGNIOL-VILLARD int x; 36059829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 36159829cc1SJean-Christophe PLAGNIOL-VILLARD addr = flash_make_addr (info, sect, offset); 36259829cc1SJean-Christophe PLAGNIOL-VILLARD 36359829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 36459829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("long addr is at %p info->portwidth = %d\n", addr, 36559829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth); 36659829cc1SJean-Christophe PLAGNIOL-VILLARD for (x = 0; x < 4 * info->portwidth; x++) { 36759829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("addr[%x] = 0x%x\n", x, addr[x]); 36859829cc1SJean-Christophe PLAGNIOL-VILLARD } 36959829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 37059829cc1SJean-Christophe PLAGNIOL-VILLARD #if defined(__LITTLE_ENDIAN) || defined(CFG_WRITE_SWAPPED_DATA) 37159829cc1SJean-Christophe PLAGNIOL-VILLARD retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) | 3727e5b9b47SHaavard Skinnemoen (addr[(2 * info->portwidth)]) | 3737e5b9b47SHaavard Skinnemoen (addr[(3 * info->portwidth)] << 8); 37459829cc1SJean-Christophe PLAGNIOL-VILLARD #else 37559829cc1SJean-Christophe PLAGNIOL-VILLARD retval = (addr[(2 * info->portwidth) - 1] << 24) | 37659829cc1SJean-Christophe PLAGNIOL-VILLARD (addr[(info->portwidth) - 1] << 16) | 37759829cc1SJean-Christophe PLAGNIOL-VILLARD (addr[(4 * info->portwidth) - 1] << 8) | 37859829cc1SJean-Christophe PLAGNIOL-VILLARD addr[(3 * info->portwidth) - 1]; 37959829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 38059829cc1SJean-Christophe PLAGNIOL-VILLARD return retval; 38159829cc1SJean-Christophe PLAGNIOL-VILLARD } 38259829cc1SJean-Christophe PLAGNIOL-VILLARD 383be60a902SHaavard Skinnemoen /* 384be60a902SHaavard Skinnemoen * Write a proper sized command to the correct address 38581b20cccSMichael Schwingen */ 386be60a902SHaavard Skinnemoen static void flash_write_cmd (flash_info_t * info, flash_sect_t sect, 387be60a902SHaavard Skinnemoen uint offset, uchar cmd) 38881b20cccSMichael Schwingen { 3897e5b9b47SHaavard Skinnemoen 390*cdbaefb5SHaavard Skinnemoen void *addr; 391be60a902SHaavard Skinnemoen cfiword_t cword; 39281b20cccSMichael Schwingen 393*cdbaefb5SHaavard Skinnemoen addr = flash_make_addr (info, sect, offset); 394be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 395be60a902SHaavard Skinnemoen switch (info->portwidth) { 396be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 397*cdbaefb5SHaavard Skinnemoen debug ("fwc addr %p cmd %x %x 8bit x %d bit\n", addr, cmd, 398be60a902SHaavard Skinnemoen cword.c, info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 399*cdbaefb5SHaavard Skinnemoen flash_write8(cword.c, addr); 400be60a902SHaavard Skinnemoen break; 401be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 402*cdbaefb5SHaavard Skinnemoen debug ("fwc addr %p cmd %x %4.4x 16bit x %d bit\n", addr, 403be60a902SHaavard Skinnemoen cmd, cword.w, 404be60a902SHaavard Skinnemoen info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 405*cdbaefb5SHaavard Skinnemoen flash_write16(cword.w, addr); 406be60a902SHaavard Skinnemoen break; 407be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 408*cdbaefb5SHaavard Skinnemoen debug ("fwc addr %p cmd %x %8.8lx 32bit x %d bit\n", addr, 409be60a902SHaavard Skinnemoen cmd, cword.l, 410be60a902SHaavard Skinnemoen info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 411*cdbaefb5SHaavard Skinnemoen flash_write32(cword.l, addr); 412be60a902SHaavard Skinnemoen break; 413be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 414be60a902SHaavard Skinnemoen #ifdef DEBUG 415be60a902SHaavard Skinnemoen { 416be60a902SHaavard Skinnemoen char str[20]; 417be60a902SHaavard Skinnemoen 418be60a902SHaavard Skinnemoen print_longlong (str, cword.ll); 419be60a902SHaavard Skinnemoen 420be60a902SHaavard Skinnemoen debug ("fwrite addr %p cmd %x %s 64 bit x %d bit\n", 421*cdbaefb5SHaavard Skinnemoen addr, cmd, str, 422be60a902SHaavard Skinnemoen info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 42381b20cccSMichael Schwingen } 424be60a902SHaavard Skinnemoen #endif 425*cdbaefb5SHaavard Skinnemoen flash_write64(cword.ll, addr); 42681b20cccSMichael Schwingen break; 42781b20cccSMichael Schwingen } 428be60a902SHaavard Skinnemoen 429be60a902SHaavard Skinnemoen /* Ensure all the instructions are fully finished */ 430be60a902SHaavard Skinnemoen sync(); 43181b20cccSMichael Schwingen } 4327e5b9b47SHaavard Skinnemoen 433be60a902SHaavard Skinnemoen static void flash_unlock_seq (flash_info_t * info, flash_sect_t sect) 434be60a902SHaavard Skinnemoen { 435be60a902SHaavard Skinnemoen flash_write_cmd (info, sect, info->addr_unlock1, AMD_CMD_UNLOCK_START); 436be60a902SHaavard Skinnemoen flash_write_cmd (info, sect, info->addr_unlock2, AMD_CMD_UNLOCK_ACK); 437be60a902SHaavard Skinnemoen } 438be60a902SHaavard Skinnemoen 439be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 440be60a902SHaavard Skinnemoen */ 441be60a902SHaavard Skinnemoen static int flash_isequal (flash_info_t * info, flash_sect_t sect, 442be60a902SHaavard Skinnemoen uint offset, uchar cmd) 443be60a902SHaavard Skinnemoen { 444*cdbaefb5SHaavard Skinnemoen void *addr; 445be60a902SHaavard Skinnemoen cfiword_t cword; 446be60a902SHaavard Skinnemoen int retval; 447be60a902SHaavard Skinnemoen 448*cdbaefb5SHaavard Skinnemoen addr = flash_make_addr (info, sect, offset); 449be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 450be60a902SHaavard Skinnemoen 451*cdbaefb5SHaavard Skinnemoen debug ("is= cmd %x(%c) addr %p ", cmd, cmd, addr); 452be60a902SHaavard Skinnemoen switch (info->portwidth) { 453be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 454*cdbaefb5SHaavard Skinnemoen debug ("is= %x %x\n", flash_read8(addr), cword.c); 455*cdbaefb5SHaavard Skinnemoen retval = (flash_read8(addr) == cword.c); 456be60a902SHaavard Skinnemoen break; 457be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 458*cdbaefb5SHaavard Skinnemoen debug ("is= %4.4x %4.4x\n", flash_read16(addr), cword.w); 459*cdbaefb5SHaavard Skinnemoen retval = (flash_read16(addr) == cword.w); 460be60a902SHaavard Skinnemoen break; 461be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 462*cdbaefb5SHaavard Skinnemoen debug ("is= %8.8lx %8.8lx\n", flash_read32(addr), cword.l); 463*cdbaefb5SHaavard Skinnemoen retval = (flash_read32(addr) == cword.l); 464be60a902SHaavard Skinnemoen break; 465be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 466be60a902SHaavard Skinnemoen #ifdef DEBUG 467be60a902SHaavard Skinnemoen { 468be60a902SHaavard Skinnemoen char str1[20]; 469be60a902SHaavard Skinnemoen char str2[20]; 470be60a902SHaavard Skinnemoen 471*cdbaefb5SHaavard Skinnemoen print_longlong (str1, flash_read64(addr)); 472be60a902SHaavard Skinnemoen print_longlong (str2, cword.ll); 473be60a902SHaavard Skinnemoen debug ("is= %s %s\n", str1, str2); 474be60a902SHaavard Skinnemoen } 475be60a902SHaavard Skinnemoen #endif 476*cdbaefb5SHaavard Skinnemoen retval = (flash_read64(addr) == cword.ll); 477be60a902SHaavard Skinnemoen break; 478be60a902SHaavard Skinnemoen default: 479be60a902SHaavard Skinnemoen retval = 0; 480be60a902SHaavard Skinnemoen break; 481be60a902SHaavard Skinnemoen } 482be60a902SHaavard Skinnemoen return retval; 483be60a902SHaavard Skinnemoen } 484be60a902SHaavard Skinnemoen 485be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 486be60a902SHaavard Skinnemoen */ 487be60a902SHaavard Skinnemoen static int flash_isset (flash_info_t * info, flash_sect_t sect, 488be60a902SHaavard Skinnemoen uint offset, uchar cmd) 489be60a902SHaavard Skinnemoen { 490*cdbaefb5SHaavard Skinnemoen void *addr; 491be60a902SHaavard Skinnemoen cfiword_t cword; 492be60a902SHaavard Skinnemoen int retval; 493be60a902SHaavard Skinnemoen 494*cdbaefb5SHaavard Skinnemoen addr = flash_make_addr (info, sect, offset); 495be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 496be60a902SHaavard Skinnemoen switch (info->portwidth) { 497be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 498*cdbaefb5SHaavard Skinnemoen retval = ((flash_read8(addr) & cword.c) == cword.c); 499be60a902SHaavard Skinnemoen break; 500be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 501*cdbaefb5SHaavard Skinnemoen retval = ((flash_read16(addr) & cword.w) == cword.w); 502be60a902SHaavard Skinnemoen break; 503be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 504*cdbaefb5SHaavard Skinnemoen retval = ((flash_read16(addr) & cword.l) == cword.l); 505be60a902SHaavard Skinnemoen break; 506be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 507*cdbaefb5SHaavard Skinnemoen retval = ((flash_read64(addr) & cword.ll) == cword.ll); 508be60a902SHaavard Skinnemoen break; 509be60a902SHaavard Skinnemoen default: 510be60a902SHaavard Skinnemoen retval = 0; 511be60a902SHaavard Skinnemoen break; 512be60a902SHaavard Skinnemoen } 513be60a902SHaavard Skinnemoen return retval; 514be60a902SHaavard Skinnemoen } 515be60a902SHaavard Skinnemoen 516be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 517be60a902SHaavard Skinnemoen */ 518be60a902SHaavard Skinnemoen static int flash_toggle (flash_info_t * info, flash_sect_t sect, 519be60a902SHaavard Skinnemoen uint offset, uchar cmd) 520be60a902SHaavard Skinnemoen { 521*cdbaefb5SHaavard Skinnemoen void *addr; 522be60a902SHaavard Skinnemoen cfiword_t cword; 523be60a902SHaavard Skinnemoen int retval; 524be60a902SHaavard Skinnemoen 525*cdbaefb5SHaavard Skinnemoen addr = flash_make_addr (info, sect, offset); 526be60a902SHaavard Skinnemoen flash_make_cmd (info, cmd, &cword); 527be60a902SHaavard Skinnemoen switch (info->portwidth) { 528be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 529*cdbaefb5SHaavard Skinnemoen retval = ((flash_read8(addr) & cword.c) != 530*cdbaefb5SHaavard Skinnemoen (flash_read8(addr) & cword.c)); 531be60a902SHaavard Skinnemoen break; 532be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 533*cdbaefb5SHaavard Skinnemoen retval = ((flash_read16(addr) & cword.w) != 534*cdbaefb5SHaavard Skinnemoen (flash_read16(addr) & cword.w)); 535be60a902SHaavard Skinnemoen break; 536be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 537*cdbaefb5SHaavard Skinnemoen retval = ((flash_read32(addr) & cword.l) != 538*cdbaefb5SHaavard Skinnemoen (flash_read32(addr) & cword.l)); 539be60a902SHaavard Skinnemoen break; 540be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 541*cdbaefb5SHaavard Skinnemoen retval = ((flash_read64(addr) & cword.ll) != 542*cdbaefb5SHaavard Skinnemoen (flash_read64(addr) & cword.ll)); 543be60a902SHaavard Skinnemoen break; 544be60a902SHaavard Skinnemoen default: 545be60a902SHaavard Skinnemoen retval = 0; 546be60a902SHaavard Skinnemoen break; 547be60a902SHaavard Skinnemoen } 548be60a902SHaavard Skinnemoen return retval; 549be60a902SHaavard Skinnemoen } 550be60a902SHaavard Skinnemoen 551be60a902SHaavard Skinnemoen /* 552be60a902SHaavard Skinnemoen * flash_is_busy - check to see if the flash is busy 553be60a902SHaavard Skinnemoen * 554be60a902SHaavard Skinnemoen * This routine checks the status of the chip and returns true if the 555be60a902SHaavard Skinnemoen * chip is busy. 556be60a902SHaavard Skinnemoen */ 557be60a902SHaavard Skinnemoen static int flash_is_busy (flash_info_t * info, flash_sect_t sect) 558be60a902SHaavard Skinnemoen { 559be60a902SHaavard Skinnemoen int retval; 560be60a902SHaavard Skinnemoen 56181b20cccSMichael Schwingen switch (info->vendor) { 56281b20cccSMichael Schwingen case CFI_CMDSET_INTEL_STANDARD: 56381b20cccSMichael Schwingen case CFI_CMDSET_INTEL_EXTENDED: 564be60a902SHaavard Skinnemoen retval = !flash_isset (info, sect, 0, FLASH_STATUS_DONE); 56581b20cccSMichael Schwingen break; 56681b20cccSMichael Schwingen case CFI_CMDSET_AMD_STANDARD: 56781b20cccSMichael Schwingen case CFI_CMDSET_AMD_EXTENDED: 568be60a902SHaavard Skinnemoen #ifdef CONFIG_FLASH_CFI_LEGACY 56981b20cccSMichael Schwingen case CFI_CMDSET_AMD_LEGACY: 570be60a902SHaavard Skinnemoen #endif 571be60a902SHaavard Skinnemoen retval = flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE); 572be60a902SHaavard Skinnemoen break; 573be60a902SHaavard Skinnemoen default: 574be60a902SHaavard Skinnemoen retval = 0; 575be60a902SHaavard Skinnemoen } 576be60a902SHaavard Skinnemoen debug ("flash_is_busy: %d\n", retval); 577be60a902SHaavard Skinnemoen return retval; 578be60a902SHaavard Skinnemoen } 579be60a902SHaavard Skinnemoen 580be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 581be60a902SHaavard Skinnemoen * wait for XSR.7 to be set. Time out with an error if it does not. 582be60a902SHaavard Skinnemoen * This routine does not set the flash to read-array mode. 583be60a902SHaavard Skinnemoen */ 584be60a902SHaavard Skinnemoen static int flash_status_check (flash_info_t * info, flash_sect_t sector, 585be60a902SHaavard Skinnemoen ulong tout, char *prompt) 586be60a902SHaavard Skinnemoen { 587be60a902SHaavard Skinnemoen ulong start; 588be60a902SHaavard Skinnemoen 589be60a902SHaavard Skinnemoen #if CFG_HZ != 1000 590be60a902SHaavard Skinnemoen tout *= CFG_HZ/1000; 591be60a902SHaavard Skinnemoen #endif 592be60a902SHaavard Skinnemoen 593be60a902SHaavard Skinnemoen /* Wait for command completion */ 594be60a902SHaavard Skinnemoen start = get_timer (0); 595be60a902SHaavard Skinnemoen while (flash_is_busy (info, sector)) { 596be60a902SHaavard Skinnemoen if (get_timer (start) > tout) { 597be60a902SHaavard Skinnemoen printf ("Flash %s timeout at address %lx data %lx\n", 598be60a902SHaavard Skinnemoen prompt, info->start[sector], 599be60a902SHaavard Skinnemoen flash_read_long (info, sector, 0)); 600be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, info->cmd_reset); 601be60a902SHaavard Skinnemoen return ERR_TIMOUT; 602be60a902SHaavard Skinnemoen } 603be60a902SHaavard Skinnemoen udelay (1); /* also triggers watchdog */ 604be60a902SHaavard Skinnemoen } 605be60a902SHaavard Skinnemoen return ERR_OK; 606be60a902SHaavard Skinnemoen } 607be60a902SHaavard Skinnemoen 608be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 609be60a902SHaavard Skinnemoen * Wait for XSR.7 to be set, if it times out print an error, otherwise 610be60a902SHaavard Skinnemoen * do a full status check. 611be60a902SHaavard Skinnemoen * 612be60a902SHaavard Skinnemoen * This routine sets the flash to read-array mode. 613be60a902SHaavard Skinnemoen */ 614be60a902SHaavard Skinnemoen static int flash_full_status_check (flash_info_t * info, flash_sect_t sector, 615be60a902SHaavard Skinnemoen ulong tout, char *prompt) 616be60a902SHaavard Skinnemoen { 617be60a902SHaavard Skinnemoen int retcode; 618be60a902SHaavard Skinnemoen 619be60a902SHaavard Skinnemoen retcode = flash_status_check (info, sector, tout, prompt); 620be60a902SHaavard Skinnemoen switch (info->vendor) { 621be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 622be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 623be60a902SHaavard Skinnemoen if ((retcode == ERR_OK) 624be60a902SHaavard Skinnemoen && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) { 625be60a902SHaavard Skinnemoen retcode = ERR_INVAL; 626be60a902SHaavard Skinnemoen printf ("Flash %s error at address %lx\n", prompt, 627be60a902SHaavard Skinnemoen info->start[sector]); 628be60a902SHaavard Skinnemoen if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | 629be60a902SHaavard Skinnemoen FLASH_STATUS_PSLBS)) { 630be60a902SHaavard Skinnemoen puts ("Command Sequence Error.\n"); 631be60a902SHaavard Skinnemoen } else if (flash_isset (info, sector, 0, 632be60a902SHaavard Skinnemoen FLASH_STATUS_ECLBS)) { 633be60a902SHaavard Skinnemoen puts ("Block Erase Error.\n"); 634be60a902SHaavard Skinnemoen retcode = ERR_NOT_ERASED; 635be60a902SHaavard Skinnemoen } else if (flash_isset (info, sector, 0, 636be60a902SHaavard Skinnemoen FLASH_STATUS_PSLBS)) { 637be60a902SHaavard Skinnemoen puts ("Locking Error\n"); 638be60a902SHaavard Skinnemoen } 639be60a902SHaavard Skinnemoen if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) { 640be60a902SHaavard Skinnemoen puts ("Block locked.\n"); 641be60a902SHaavard Skinnemoen retcode = ERR_PROTECTED; 642be60a902SHaavard Skinnemoen } 643be60a902SHaavard Skinnemoen if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS)) 644be60a902SHaavard Skinnemoen puts ("Vpp Low Error.\n"); 645be60a902SHaavard Skinnemoen } 646be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, info->cmd_reset); 647be60a902SHaavard Skinnemoen break; 648be60a902SHaavard Skinnemoen default: 64981b20cccSMichael Schwingen break; 65081b20cccSMichael Schwingen } 651be60a902SHaavard Skinnemoen return retcode; 65281b20cccSMichael Schwingen } 653be60a902SHaavard Skinnemoen 654be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 655be60a902SHaavard Skinnemoen */ 656be60a902SHaavard Skinnemoen static void flash_add_byte (flash_info_t * info, cfiword_t * cword, uchar c) 657be60a902SHaavard Skinnemoen { 658be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 659be60a902SHaavard Skinnemoen unsigned short w; 660be60a902SHaavard Skinnemoen unsigned int l; 661be60a902SHaavard Skinnemoen unsigned long long ll; 662be60a902SHaavard Skinnemoen #endif 663be60a902SHaavard Skinnemoen 664be60a902SHaavard Skinnemoen switch (info->portwidth) { 665be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 666be60a902SHaavard Skinnemoen cword->c = c; 667be60a902SHaavard Skinnemoen break; 668be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 669be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 670be60a902SHaavard Skinnemoen w = c; 671be60a902SHaavard Skinnemoen w <<= 8; 672be60a902SHaavard Skinnemoen cword->w = (cword->w >> 8) | w; 67381b20cccSMichael Schwingen #else 674be60a902SHaavard Skinnemoen cword->w = (cword->w << 8) | c; 675be60a902SHaavard Skinnemoen #endif 676be60a902SHaavard Skinnemoen break; 677be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 678be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 679be60a902SHaavard Skinnemoen l = c; 680be60a902SHaavard Skinnemoen l <<= 24; 681be60a902SHaavard Skinnemoen cword->l = (cword->l >> 8) | l; 682be60a902SHaavard Skinnemoen #else 683be60a902SHaavard Skinnemoen cword->l = (cword->l << 8) | c; 684be60a902SHaavard Skinnemoen #endif 685be60a902SHaavard Skinnemoen break; 686be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 687be60a902SHaavard Skinnemoen #if defined(__LITTLE_ENDIAN) && !defined(CFG_WRITE_SWAPPED_DATA) 688be60a902SHaavard Skinnemoen ll = c; 689be60a902SHaavard Skinnemoen ll <<= 56; 690be60a902SHaavard Skinnemoen cword->ll = (cword->ll >> 8) | ll; 691be60a902SHaavard Skinnemoen #else 692be60a902SHaavard Skinnemoen cword->ll = (cword->ll << 8) | c; 693be60a902SHaavard Skinnemoen #endif 694be60a902SHaavard Skinnemoen break; 695be60a902SHaavard Skinnemoen } 696be60a902SHaavard Skinnemoen } 697be60a902SHaavard Skinnemoen 698be60a902SHaavard Skinnemoen /* loop through the sectors from the highest address when the passed 699be60a902SHaavard Skinnemoen * address is greater or equal to the sector address we have a match 700be60a902SHaavard Skinnemoen */ 701be60a902SHaavard Skinnemoen static flash_sect_t find_sector (flash_info_t * info, ulong addr) 70281b20cccSMichael Schwingen { 703be60a902SHaavard Skinnemoen flash_sect_t sector; 704be60a902SHaavard Skinnemoen 705be60a902SHaavard Skinnemoen for (sector = info->sector_count - 1; sector >= 0; sector--) { 706be60a902SHaavard Skinnemoen if (addr >= info->start[sector]) 707be60a902SHaavard Skinnemoen break; 70881b20cccSMichael Schwingen } 709be60a902SHaavard Skinnemoen return sector; 71059829cc1SJean-Christophe PLAGNIOL-VILLARD } 71159829cc1SJean-Christophe PLAGNIOL-VILLARD 71259829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 71359829cc1SJean-Christophe PLAGNIOL-VILLARD */ 714be60a902SHaavard Skinnemoen static int flash_write_cfiword (flash_info_t * info, ulong dest, 715be60a902SHaavard Skinnemoen cfiword_t cword) 71659829cc1SJean-Christophe PLAGNIOL-VILLARD { 717*cdbaefb5SHaavard Skinnemoen void *ctladdr; 718*cdbaefb5SHaavard Skinnemoen void *dstaddr; 719be60a902SHaavard Skinnemoen int flag; 72059829cc1SJean-Christophe PLAGNIOL-VILLARD 721*cdbaefb5SHaavard Skinnemoen ctladdr = flash_make_addr (info, 0, 0); 722*cdbaefb5SHaavard Skinnemoen dstaddr = (uchar *)dest; 723be60a902SHaavard Skinnemoen 724be60a902SHaavard Skinnemoen /* Check if Flash is (sufficiently) erased */ 725be60a902SHaavard Skinnemoen switch (info->portwidth) { 726be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 727*cdbaefb5SHaavard Skinnemoen flag = ((flash_read8(dstaddr) & cword.c) == cword.c); 728be60a902SHaavard Skinnemoen break; 729be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 730*cdbaefb5SHaavard Skinnemoen flag = ((flash_read16(dstaddr) & cword.w) == cword.w); 731be60a902SHaavard Skinnemoen break; 732be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 733*cdbaefb5SHaavard Skinnemoen flag = ((flash_read32(dstaddr) & cword.l) == cword.l); 734be60a902SHaavard Skinnemoen break; 735be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 736*cdbaefb5SHaavard Skinnemoen flag = ((flash_read64(dstaddr) & cword.ll) == cword.ll); 737be60a902SHaavard Skinnemoen break; 738be60a902SHaavard Skinnemoen default: 739be60a902SHaavard Skinnemoen return 2; 740be60a902SHaavard Skinnemoen } 741be60a902SHaavard Skinnemoen if (!flag) 742be60a902SHaavard Skinnemoen return 2; 743be60a902SHaavard Skinnemoen 744be60a902SHaavard Skinnemoen /* Disable interrupts which might cause a timeout here */ 745be60a902SHaavard Skinnemoen flag = disable_interrupts (); 746be60a902SHaavard Skinnemoen 747be60a902SHaavard Skinnemoen switch (info->vendor) { 748be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 749be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 750be60a902SHaavard Skinnemoen flash_write_cmd (info, 0, 0, FLASH_CMD_CLEAR_STATUS); 751be60a902SHaavard Skinnemoen flash_write_cmd (info, 0, 0, FLASH_CMD_WRITE); 752be60a902SHaavard Skinnemoen break; 753be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_EXTENDED: 754be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_STANDARD: 755be60a902SHaavard Skinnemoen #ifdef CONFIG_FLASH_CFI_LEGACY 756be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_LEGACY: 757be60a902SHaavard Skinnemoen #endif 758be60a902SHaavard Skinnemoen flash_unlock_seq (info, 0); 759be60a902SHaavard Skinnemoen flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_WRITE); 76059829cc1SJean-Christophe PLAGNIOL-VILLARD break; 76159829cc1SJean-Christophe PLAGNIOL-VILLARD } 76259829cc1SJean-Christophe PLAGNIOL-VILLARD 763be60a902SHaavard Skinnemoen switch (info->portwidth) { 764be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 765*cdbaefb5SHaavard Skinnemoen flash_write8(cword.c, dstaddr); 766be60a902SHaavard Skinnemoen break; 767be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 768*cdbaefb5SHaavard Skinnemoen flash_write16(cword.w, dstaddr); 769be60a902SHaavard Skinnemoen break; 770be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 771*cdbaefb5SHaavard Skinnemoen flash_write32(cword.l, dstaddr); 772be60a902SHaavard Skinnemoen break; 773be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 774*cdbaefb5SHaavard Skinnemoen flash_write64(cword.ll, dstaddr); 775be60a902SHaavard Skinnemoen break; 77659829cc1SJean-Christophe PLAGNIOL-VILLARD } 777be60a902SHaavard Skinnemoen 778be60a902SHaavard Skinnemoen /* re-enable interrupts if necessary */ 779be60a902SHaavard Skinnemoen if (flag) 780be60a902SHaavard Skinnemoen enable_interrupts (); 781be60a902SHaavard Skinnemoen 782be60a902SHaavard Skinnemoen return flash_full_status_check (info, find_sector (info, dest), 783be60a902SHaavard Skinnemoen info->write_tout, "write"); 784be60a902SHaavard Skinnemoen } 785be60a902SHaavard Skinnemoen 786be60a902SHaavard Skinnemoen #ifdef CFG_FLASH_USE_BUFFER_WRITE 787be60a902SHaavard Skinnemoen 788be60a902SHaavard Skinnemoen static int flash_write_cfibuffer (flash_info_t * info, ulong dest, uchar * cp, 789be60a902SHaavard Skinnemoen int len) 790be60a902SHaavard Skinnemoen { 791be60a902SHaavard Skinnemoen flash_sect_t sector; 792be60a902SHaavard Skinnemoen int cnt; 793be60a902SHaavard Skinnemoen int retcode; 794*cdbaefb5SHaavard Skinnemoen void *src = cp; 795*cdbaefb5SHaavard Skinnemoen void *dst = (void *)dest; 796*cdbaefb5SHaavard Skinnemoen 797*cdbaefb5SHaavard Skinnemoen sector = find_sector (info, dest); 798be60a902SHaavard Skinnemoen 799be60a902SHaavard Skinnemoen switch (info->vendor) { 800be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 801be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 802be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); 803be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER); 804be60a902SHaavard Skinnemoen retcode = flash_status_check (info, sector, 805be60a902SHaavard Skinnemoen info->buffer_write_tout, 806be60a902SHaavard Skinnemoen "write to buffer"); 807be60a902SHaavard Skinnemoen if (retcode == ERR_OK) { 808be60a902SHaavard Skinnemoen /* reduce the number of loops by the width of 809be60a902SHaavard Skinnemoen * the port */ 810be60a902SHaavard Skinnemoen switch (info->portwidth) { 811be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 812be60a902SHaavard Skinnemoen cnt = len; 813be60a902SHaavard Skinnemoen break; 814be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 815be60a902SHaavard Skinnemoen cnt = len >> 1; 816be60a902SHaavard Skinnemoen break; 817be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 818be60a902SHaavard Skinnemoen cnt = len >> 2; 819be60a902SHaavard Skinnemoen break; 820be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 821be60a902SHaavard Skinnemoen cnt = len >> 3; 822be60a902SHaavard Skinnemoen break; 823be60a902SHaavard Skinnemoen default: 824be60a902SHaavard Skinnemoen return ERR_INVAL; 825be60a902SHaavard Skinnemoen break; 826be60a902SHaavard Skinnemoen } 827be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 828be60a902SHaavard Skinnemoen while (cnt-- > 0) { 829be60a902SHaavard Skinnemoen switch (info->portwidth) { 830be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 831*cdbaefb5SHaavard Skinnemoen flash_write8(flash_read8(src), dst); 832*cdbaefb5SHaavard Skinnemoen src += 1, dst += 1; 833be60a902SHaavard Skinnemoen break; 834be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 835*cdbaefb5SHaavard Skinnemoen flash_write16(flash_read16(src), dst); 836*cdbaefb5SHaavard Skinnemoen src += 2, dst += 2; 837be60a902SHaavard Skinnemoen break; 838be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 839*cdbaefb5SHaavard Skinnemoen flash_write32(flash_read32(src), dst); 840*cdbaefb5SHaavard Skinnemoen src += 4, dst += 4; 841be60a902SHaavard Skinnemoen break; 842be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 843*cdbaefb5SHaavard Skinnemoen flash_write64(flash_read64(src), dst); 844*cdbaefb5SHaavard Skinnemoen src += 8, dst += 8; 845be60a902SHaavard Skinnemoen break; 846be60a902SHaavard Skinnemoen default: 847be60a902SHaavard Skinnemoen return ERR_INVAL; 848be60a902SHaavard Skinnemoen break; 849be60a902SHaavard Skinnemoen } 850be60a902SHaavard Skinnemoen } 851be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, 852be60a902SHaavard Skinnemoen FLASH_CMD_WRITE_BUFFER_CONFIRM); 853be60a902SHaavard Skinnemoen retcode = flash_full_status_check ( 854be60a902SHaavard Skinnemoen info, sector, info->buffer_write_tout, 855be60a902SHaavard Skinnemoen "buffer write"); 856be60a902SHaavard Skinnemoen } 857be60a902SHaavard Skinnemoen return retcode; 858be60a902SHaavard Skinnemoen 859be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_STANDARD: 860be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_EXTENDED: 861be60a902SHaavard Skinnemoen flash_unlock_seq(info,0); 862be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_TO_BUFFER); 863be60a902SHaavard Skinnemoen 864be60a902SHaavard Skinnemoen switch (info->portwidth) { 865be60a902SHaavard Skinnemoen case FLASH_CFI_8BIT: 866be60a902SHaavard Skinnemoen cnt = len; 867be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 868*cdbaefb5SHaavard Skinnemoen while (cnt-- > 0) { 869*cdbaefb5SHaavard Skinnemoen flash_write8(flash_read8(src), dst); 870*cdbaefb5SHaavard Skinnemoen src += 1, dst += 1; 871*cdbaefb5SHaavard Skinnemoen } 872be60a902SHaavard Skinnemoen break; 873be60a902SHaavard Skinnemoen case FLASH_CFI_16BIT: 874be60a902SHaavard Skinnemoen cnt = len >> 1; 875be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 876*cdbaefb5SHaavard Skinnemoen while (cnt-- > 0) { 877*cdbaefb5SHaavard Skinnemoen flash_write16(flash_read16(src), dst); 878*cdbaefb5SHaavard Skinnemoen src += 2, dst += 2; 879*cdbaefb5SHaavard Skinnemoen } 880be60a902SHaavard Skinnemoen break; 881be60a902SHaavard Skinnemoen case FLASH_CFI_32BIT: 882be60a902SHaavard Skinnemoen cnt = len >> 2; 883be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 884*cdbaefb5SHaavard Skinnemoen while (cnt-- > 0) { 885*cdbaefb5SHaavard Skinnemoen flash_write32(flash_read32(src), dst); 886*cdbaefb5SHaavard Skinnemoen src += 4, dst += 4; 887*cdbaefb5SHaavard Skinnemoen } 888be60a902SHaavard Skinnemoen break; 889be60a902SHaavard Skinnemoen case FLASH_CFI_64BIT: 890be60a902SHaavard Skinnemoen cnt = len >> 3; 891be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, (uchar) cnt - 1); 892*cdbaefb5SHaavard Skinnemoen while (cnt-- > 0) { 893*cdbaefb5SHaavard Skinnemoen flash_write64(flash_read64(src), dst); 894*cdbaefb5SHaavard Skinnemoen src += 8, dst += 8; 895*cdbaefb5SHaavard Skinnemoen } 896be60a902SHaavard Skinnemoen break; 897be60a902SHaavard Skinnemoen default: 898be60a902SHaavard Skinnemoen return ERR_INVAL; 899be60a902SHaavard Skinnemoen } 900be60a902SHaavard Skinnemoen 901be60a902SHaavard Skinnemoen flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM); 902be60a902SHaavard Skinnemoen retcode = flash_full_status_check (info, sector, 903be60a902SHaavard Skinnemoen info->buffer_write_tout, 904be60a902SHaavard Skinnemoen "buffer write"); 905be60a902SHaavard Skinnemoen return retcode; 906be60a902SHaavard Skinnemoen 907be60a902SHaavard Skinnemoen default: 908be60a902SHaavard Skinnemoen debug ("Unknown Command Set\n"); 909be60a902SHaavard Skinnemoen return ERR_INVAL; 910be60a902SHaavard Skinnemoen } 911be60a902SHaavard Skinnemoen } 912be60a902SHaavard Skinnemoen #endif /* CFG_FLASH_USE_BUFFER_WRITE */ 913be60a902SHaavard Skinnemoen 91459829cc1SJean-Christophe PLAGNIOL-VILLARD 91559829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 91659829cc1SJean-Christophe PLAGNIOL-VILLARD */ 91759829cc1SJean-Christophe PLAGNIOL-VILLARD int flash_erase (flash_info_t * info, int s_first, int s_last) 91859829cc1SJean-Christophe PLAGNIOL-VILLARD { 91959829cc1SJean-Christophe PLAGNIOL-VILLARD int rcode = 0; 92059829cc1SJean-Christophe PLAGNIOL-VILLARD int prot; 92159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_sect_t sect; 92259829cc1SJean-Christophe PLAGNIOL-VILLARD 92359829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->flash_id != FLASH_MAN_CFI) { 92459829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("Can't erase unknown flash type - aborted\n"); 92559829cc1SJean-Christophe PLAGNIOL-VILLARD return 1; 92659829cc1SJean-Christophe PLAGNIOL-VILLARD } 92759829cc1SJean-Christophe PLAGNIOL-VILLARD if ((s_first < 0) || (s_first > s_last)) { 92859829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("- no sectors to erase\n"); 92959829cc1SJean-Christophe PLAGNIOL-VILLARD return 1; 93059829cc1SJean-Christophe PLAGNIOL-VILLARD } 93159829cc1SJean-Christophe PLAGNIOL-VILLARD 93259829cc1SJean-Christophe PLAGNIOL-VILLARD prot = 0; 93359829cc1SJean-Christophe PLAGNIOL-VILLARD for (sect = s_first; sect <= s_last; ++sect) { 93459829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->protect[sect]) { 93559829cc1SJean-Christophe PLAGNIOL-VILLARD prot++; 93659829cc1SJean-Christophe PLAGNIOL-VILLARD } 93759829cc1SJean-Christophe PLAGNIOL-VILLARD } 93859829cc1SJean-Christophe PLAGNIOL-VILLARD if (prot) { 9397e5b9b47SHaavard Skinnemoen printf ("- Warning: %d protected sectors will not be erased!\n", 9407e5b9b47SHaavard Skinnemoen prot); 94159829cc1SJean-Christophe PLAGNIOL-VILLARD } else { 94259829cc1SJean-Christophe PLAGNIOL-VILLARD putc ('\n'); 94359829cc1SJean-Christophe PLAGNIOL-VILLARD } 94459829cc1SJean-Christophe PLAGNIOL-VILLARD 94559829cc1SJean-Christophe PLAGNIOL-VILLARD 94659829cc1SJean-Christophe PLAGNIOL-VILLARD for (sect = s_first; sect <= s_last; sect++) { 94759829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->protect[sect] == 0) { /* not protected */ 94859829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 94959829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 95059829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 9517e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9527e5b9b47SHaavard Skinnemoen FLASH_CMD_CLEAR_STATUS); 9537e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9547e5b9b47SHaavard Skinnemoen FLASH_CMD_BLOCK_ERASE); 9557e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9567e5b9b47SHaavard Skinnemoen FLASH_CMD_ERASE_CONFIRM); 95759829cc1SJean-Christophe PLAGNIOL-VILLARD break; 95859829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 95959829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 96059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_unlock_seq (info, sect); 9617e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 9627e5b9b47SHaavard Skinnemoen info->addr_unlock1, 9637e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_START); 96459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_unlock_seq (info, sect); 9657e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9667e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_SECTOR); 96759829cc1SJean-Christophe PLAGNIOL-VILLARD break; 96881b20cccSMichael Schwingen #ifdef CONFIG_FLASH_CFI_LEGACY 96981b20cccSMichael Schwingen case CFI_CMDSET_AMD_LEGACY: 97081b20cccSMichael Schwingen flash_unlock_seq (info, 0); 9717e5b9b47SHaavard Skinnemoen flash_write_cmd (info, 0, info->addr_unlock1, 9727e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_START); 97381b20cccSMichael Schwingen flash_unlock_seq (info, 0); 9747e5b9b47SHaavard Skinnemoen flash_write_cmd (info, sect, 0, 9757e5b9b47SHaavard Skinnemoen AMD_CMD_ERASE_SECTOR); 97681b20cccSMichael Schwingen break; 97781b20cccSMichael Schwingen #endif 97859829cc1SJean-Christophe PLAGNIOL-VILLARD default: 97959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("Unkown flash vendor %d\n", 98059829cc1SJean-Christophe PLAGNIOL-VILLARD info->vendor); 98159829cc1SJean-Christophe PLAGNIOL-VILLARD break; 98259829cc1SJean-Christophe PLAGNIOL-VILLARD } 98359829cc1SJean-Christophe PLAGNIOL-VILLARD 98459829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_full_status_check 98559829cc1SJean-Christophe PLAGNIOL-VILLARD (info, sect, info->erase_blk_tout, "erase")) { 98659829cc1SJean-Christophe PLAGNIOL-VILLARD rcode = 1; 98759829cc1SJean-Christophe PLAGNIOL-VILLARD } else 98859829cc1SJean-Christophe PLAGNIOL-VILLARD putc ('.'); 98959829cc1SJean-Christophe PLAGNIOL-VILLARD } 99059829cc1SJean-Christophe PLAGNIOL-VILLARD } 99159829cc1SJean-Christophe PLAGNIOL-VILLARD puts (" done\n"); 99259829cc1SJean-Christophe PLAGNIOL-VILLARD return rcode; 99359829cc1SJean-Christophe PLAGNIOL-VILLARD } 99459829cc1SJean-Christophe PLAGNIOL-VILLARD 99559829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 99659829cc1SJean-Christophe PLAGNIOL-VILLARD */ 99759829cc1SJean-Christophe PLAGNIOL-VILLARD void flash_print_info (flash_info_t * info) 99859829cc1SJean-Christophe PLAGNIOL-VILLARD { 99959829cc1SJean-Christophe PLAGNIOL-VILLARD int i; 100059829cc1SJean-Christophe PLAGNIOL-VILLARD 100159829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->flash_id != FLASH_MAN_CFI) { 100259829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("missing or unknown FLASH type\n"); 100359829cc1SJean-Christophe PLAGNIOL-VILLARD return; 100459829cc1SJean-Christophe PLAGNIOL-VILLARD } 100559829cc1SJean-Christophe PLAGNIOL-VILLARD 100681b20cccSMichael Schwingen printf ("%s FLASH (%d x %d)", 100781b20cccSMichael Schwingen info->name, 100859829cc1SJean-Christophe PLAGNIOL-VILLARD (info->portwidth << 3), (info->chipwidth << 3)); 100981b20cccSMichael Schwingen if (info->size < 1024*1024) 101081b20cccSMichael Schwingen printf (" Size: %ld kB in %d Sectors\n", 101181b20cccSMichael Schwingen info->size >> 10, info->sector_count); 101281b20cccSMichael Schwingen else 101359829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" Size: %ld MB in %d Sectors\n", 101459829cc1SJean-Christophe PLAGNIOL-VILLARD info->size >> 20, info->sector_count); 101559829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" "); 101659829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 101759829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 101859829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("Intel Standard"); 101959829cc1SJean-Christophe PLAGNIOL-VILLARD break; 102059829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 102159829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("Intel Extended"); 102259829cc1SJean-Christophe PLAGNIOL-VILLARD break; 102359829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 102459829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("AMD Standard"); 102559829cc1SJean-Christophe PLAGNIOL-VILLARD break; 102659829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 102759829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("AMD Extended"); 102859829cc1SJean-Christophe PLAGNIOL-VILLARD break; 102981b20cccSMichael Schwingen #ifdef CONFIG_FLASH_CFI_LEGACY 103081b20cccSMichael Schwingen case CFI_CMDSET_AMD_LEGACY: 103181b20cccSMichael Schwingen printf ("AMD Legacy"); 103281b20cccSMichael Schwingen break; 103381b20cccSMichael Schwingen #endif 103459829cc1SJean-Christophe PLAGNIOL-VILLARD default: 103559829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("Unknown (%d)", info->vendor); 103659829cc1SJean-Christophe PLAGNIOL-VILLARD break; 103759829cc1SJean-Christophe PLAGNIOL-VILLARD } 103859829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X", 103959829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id, info->device_id); 104059829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->device_id == 0x7E) { 104159829cc1SJean-Christophe PLAGNIOL-VILLARD printf("%04X", info->device_id2); 104259829cc1SJean-Christophe PLAGNIOL-VILLARD } 104359829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("\n Erase timeout: %ld ms, write timeout: %ld ms\n", 104459829cc1SJean-Christophe PLAGNIOL-VILLARD info->erase_blk_tout, 104559829cc1SJean-Christophe PLAGNIOL-VILLARD info->write_tout); 104659829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->buffer_size > 1) { 10477e5b9b47SHaavard Skinnemoen printf (" Buffer write timeout: %ld ms, " 10487e5b9b47SHaavard Skinnemoen "buffer size: %d bytes\n", 104959829cc1SJean-Christophe PLAGNIOL-VILLARD info->buffer_write_tout, 105059829cc1SJean-Christophe PLAGNIOL-VILLARD info->buffer_size); 105159829cc1SJean-Christophe PLAGNIOL-VILLARD } 105259829cc1SJean-Christophe PLAGNIOL-VILLARD 105359829cc1SJean-Christophe PLAGNIOL-VILLARD puts ("\n Sector Start Addresses:"); 105459829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->sector_count; ++i) { 105559829cc1SJean-Christophe PLAGNIOL-VILLARD if ((i % 5) == 0) 105659829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("\n"); 105759829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_EMPTY_INFO 105859829cc1SJean-Christophe PLAGNIOL-VILLARD int k; 105959829cc1SJean-Christophe PLAGNIOL-VILLARD int size; 106059829cc1SJean-Christophe PLAGNIOL-VILLARD int erased; 106159829cc1SJean-Christophe PLAGNIOL-VILLARD volatile unsigned long *flash; 106259829cc1SJean-Christophe PLAGNIOL-VILLARD 106359829cc1SJean-Christophe PLAGNIOL-VILLARD /* 106459829cc1SJean-Christophe PLAGNIOL-VILLARD * Check if whole sector is erased 106559829cc1SJean-Christophe PLAGNIOL-VILLARD */ 106659829cc1SJean-Christophe PLAGNIOL-VILLARD if (i != (info->sector_count - 1)) 106759829cc1SJean-Christophe PLAGNIOL-VILLARD size = info->start[i + 1] - info->start[i]; 106859829cc1SJean-Christophe PLAGNIOL-VILLARD else 106959829cc1SJean-Christophe PLAGNIOL-VILLARD size = info->start[0] + info->size - info->start[i]; 107059829cc1SJean-Christophe PLAGNIOL-VILLARD erased = 1; 107159829cc1SJean-Christophe PLAGNIOL-VILLARD flash = (volatile unsigned long *) info->start[i]; 107259829cc1SJean-Christophe PLAGNIOL-VILLARD size = size >> 2; /* divide by 4 for longword access */ 107359829cc1SJean-Christophe PLAGNIOL-VILLARD for (k = 0; k < size; k++) { 107459829cc1SJean-Christophe PLAGNIOL-VILLARD if (*flash++ != 0xffffffff) { 107559829cc1SJean-Christophe PLAGNIOL-VILLARD erased = 0; 107659829cc1SJean-Christophe PLAGNIOL-VILLARD break; 107759829cc1SJean-Christophe PLAGNIOL-VILLARD } 107859829cc1SJean-Christophe PLAGNIOL-VILLARD } 107959829cc1SJean-Christophe PLAGNIOL-VILLARD 108059829cc1SJean-Christophe PLAGNIOL-VILLARD /* print empty and read-only info */ 108159829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" %08lX %c %s ", 108259829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[i], 108359829cc1SJean-Christophe PLAGNIOL-VILLARD erased ? 'E' : ' ', 108459829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[i] ? "RO" : " "); 108559829cc1SJean-Christophe PLAGNIOL-VILLARD #else /* ! CFG_FLASH_EMPTY_INFO */ 108659829cc1SJean-Christophe PLAGNIOL-VILLARD printf (" %08lX %s ", 108759829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[i], 108859829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[i] ? "RO" : " "); 108959829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 109059829cc1SJean-Christophe PLAGNIOL-VILLARD } 109159829cc1SJean-Christophe PLAGNIOL-VILLARD putc ('\n'); 109259829cc1SJean-Christophe PLAGNIOL-VILLARD return; 109359829cc1SJean-Christophe PLAGNIOL-VILLARD } 109459829cc1SJean-Christophe PLAGNIOL-VILLARD 109559829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 109659829cc1SJean-Christophe PLAGNIOL-VILLARD * Copy memory to flash, returns: 109759829cc1SJean-Christophe PLAGNIOL-VILLARD * 0 - OK 109859829cc1SJean-Christophe PLAGNIOL-VILLARD * 1 - write timeout 109959829cc1SJean-Christophe PLAGNIOL-VILLARD * 2 - Flash not erased 110059829cc1SJean-Christophe PLAGNIOL-VILLARD */ 110159829cc1SJean-Christophe PLAGNIOL-VILLARD int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) 110259829cc1SJean-Christophe PLAGNIOL-VILLARD { 110359829cc1SJean-Christophe PLAGNIOL-VILLARD ulong wp; 110459829cc1SJean-Christophe PLAGNIOL-VILLARD ulong cp; 110559829cc1SJean-Christophe PLAGNIOL-VILLARD int aln; 110659829cc1SJean-Christophe PLAGNIOL-VILLARD cfiword_t cword; 110759829cc1SJean-Christophe PLAGNIOL-VILLARD int i, rc; 110859829cc1SJean-Christophe PLAGNIOL-VILLARD 110959829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_USE_BUFFER_WRITE 111059829cc1SJean-Christophe PLAGNIOL-VILLARD int buffered_size; 111159829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 111259829cc1SJean-Christophe PLAGNIOL-VILLARD /* get lower aligned address */ 111359829cc1SJean-Christophe PLAGNIOL-VILLARD /* get lower aligned address */ 111459829cc1SJean-Christophe PLAGNIOL-VILLARD wp = (addr & ~(info->portwidth - 1)); 111559829cc1SJean-Christophe PLAGNIOL-VILLARD 111659829cc1SJean-Christophe PLAGNIOL-VILLARD /* handle unaligned start */ 111759829cc1SJean-Christophe PLAGNIOL-VILLARD if ((aln = addr - wp) != 0) { 111859829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 111959829cc1SJean-Christophe PLAGNIOL-VILLARD cp = wp; 112059829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < aln; ++i, ++cp) 112159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, (*(uchar *) cp)); 112259829cc1SJean-Christophe PLAGNIOL-VILLARD 112359829cc1SJean-Christophe PLAGNIOL-VILLARD for (; (i < info->portwidth) && (cnt > 0); i++) { 112459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 112559829cc1SJean-Christophe PLAGNIOL-VILLARD cnt--; 112659829cc1SJean-Christophe PLAGNIOL-VILLARD cp++; 112759829cc1SJean-Christophe PLAGNIOL-VILLARD } 112859829cc1SJean-Christophe PLAGNIOL-VILLARD for (; (cnt == 0) && (i < info->portwidth); ++i, ++cp) 112959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, (*(uchar *) cp)); 113059829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfiword (info, wp, cword)) != 0) 113159829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 113259829cc1SJean-Christophe PLAGNIOL-VILLARD wp = cp; 113359829cc1SJean-Christophe PLAGNIOL-VILLARD } 113459829cc1SJean-Christophe PLAGNIOL-VILLARD 113559829cc1SJean-Christophe PLAGNIOL-VILLARD /* handle the aligned part */ 113659829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_USE_BUFFER_WRITE 113759829cc1SJean-Christophe PLAGNIOL-VILLARD buffered_size = (info->portwidth / info->chipwidth); 113859829cc1SJean-Christophe PLAGNIOL-VILLARD buffered_size *= info->buffer_size; 113959829cc1SJean-Christophe PLAGNIOL-VILLARD while (cnt >= info->portwidth) { 114059829cc1SJean-Christophe PLAGNIOL-VILLARD /* prohibit buffer write when buffer_size is 1 */ 114159829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->buffer_size == 1) { 114259829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 114359829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->portwidth; i++) 114459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 114559829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfiword (info, wp, cword)) != 0) 114659829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 114759829cc1SJean-Christophe PLAGNIOL-VILLARD wp += info->portwidth; 114859829cc1SJean-Christophe PLAGNIOL-VILLARD cnt -= info->portwidth; 114959829cc1SJean-Christophe PLAGNIOL-VILLARD continue; 115059829cc1SJean-Christophe PLAGNIOL-VILLARD } 115159829cc1SJean-Christophe PLAGNIOL-VILLARD 115259829cc1SJean-Christophe PLAGNIOL-VILLARD /* write buffer until next buffered_size aligned boundary */ 115359829cc1SJean-Christophe PLAGNIOL-VILLARD i = buffered_size - (wp % buffered_size); 115459829cc1SJean-Christophe PLAGNIOL-VILLARD if (i > cnt) 115559829cc1SJean-Christophe PLAGNIOL-VILLARD i = cnt; 115659829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfibuffer (info, wp, src, i)) != ERR_OK) 115759829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 115859829cc1SJean-Christophe PLAGNIOL-VILLARD i -= i & (info->portwidth - 1); 115959829cc1SJean-Christophe PLAGNIOL-VILLARD wp += i; 116059829cc1SJean-Christophe PLAGNIOL-VILLARD src += i; 116159829cc1SJean-Christophe PLAGNIOL-VILLARD cnt -= i; 116259829cc1SJean-Christophe PLAGNIOL-VILLARD } 116359829cc1SJean-Christophe PLAGNIOL-VILLARD #else 116459829cc1SJean-Christophe PLAGNIOL-VILLARD while (cnt >= info->portwidth) { 116559829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 116659829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->portwidth; i++) { 116759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 116859829cc1SJean-Christophe PLAGNIOL-VILLARD } 116959829cc1SJean-Christophe PLAGNIOL-VILLARD if ((rc = flash_write_cfiword (info, wp, cword)) != 0) 117059829cc1SJean-Christophe PLAGNIOL-VILLARD return rc; 117159829cc1SJean-Christophe PLAGNIOL-VILLARD wp += info->portwidth; 117259829cc1SJean-Christophe PLAGNIOL-VILLARD cnt -= info->portwidth; 117359829cc1SJean-Christophe PLAGNIOL-VILLARD } 117459829cc1SJean-Christophe PLAGNIOL-VILLARD #endif /* CFG_FLASH_USE_BUFFER_WRITE */ 117559829cc1SJean-Christophe PLAGNIOL-VILLARD if (cnt == 0) { 117659829cc1SJean-Christophe PLAGNIOL-VILLARD return (0); 117759829cc1SJean-Christophe PLAGNIOL-VILLARD } 117859829cc1SJean-Christophe PLAGNIOL-VILLARD 117959829cc1SJean-Christophe PLAGNIOL-VILLARD /* 118059829cc1SJean-Christophe PLAGNIOL-VILLARD * handle unaligned tail bytes 118159829cc1SJean-Christophe PLAGNIOL-VILLARD */ 118259829cc1SJean-Christophe PLAGNIOL-VILLARD cword.l = 0; 118359829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0, cp = wp; (i < info->portwidth) && (cnt > 0); ++i, ++cp) { 118459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, *src++); 118559829cc1SJean-Christophe PLAGNIOL-VILLARD --cnt; 118659829cc1SJean-Christophe PLAGNIOL-VILLARD } 118759829cc1SJean-Christophe PLAGNIOL-VILLARD for (; i < info->portwidth; ++i, ++cp) { 118859829cc1SJean-Christophe PLAGNIOL-VILLARD flash_add_byte (info, &cword, (*(uchar *) cp)); 118959829cc1SJean-Christophe PLAGNIOL-VILLARD } 119059829cc1SJean-Christophe PLAGNIOL-VILLARD 119159829cc1SJean-Christophe PLAGNIOL-VILLARD return flash_write_cfiword (info, wp, cword); 119259829cc1SJean-Christophe PLAGNIOL-VILLARD } 119359829cc1SJean-Christophe PLAGNIOL-VILLARD 119459829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 119559829cc1SJean-Christophe PLAGNIOL-VILLARD */ 119659829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_PROTECTION 119759829cc1SJean-Christophe PLAGNIOL-VILLARD 119859829cc1SJean-Christophe PLAGNIOL-VILLARD int flash_real_protect (flash_info_t * info, long sector, int prot) 119959829cc1SJean-Christophe PLAGNIOL-VILLARD { 120059829cc1SJean-Christophe PLAGNIOL-VILLARD int retcode = 0; 120159829cc1SJean-Christophe PLAGNIOL-VILLARD 120259829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS); 120359829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT); 120459829cc1SJean-Christophe PLAGNIOL-VILLARD if (prot) 120559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET); 120659829cc1SJean-Christophe PLAGNIOL-VILLARD else 120759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR); 120859829cc1SJean-Christophe PLAGNIOL-VILLARD 120959829cc1SJean-Christophe PLAGNIOL-VILLARD if ((retcode = 121059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_full_status_check (info, sector, info->erase_blk_tout, 121159829cc1SJean-Christophe PLAGNIOL-VILLARD prot ? "protect" : "unprotect")) == 0) { 121259829cc1SJean-Christophe PLAGNIOL-VILLARD 121359829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[sector] = prot; 121459829cc1SJean-Christophe PLAGNIOL-VILLARD 121559829cc1SJean-Christophe PLAGNIOL-VILLARD /* 121659829cc1SJean-Christophe PLAGNIOL-VILLARD * On some of Intel's flash chips (marked via legacy_unlock) 121759829cc1SJean-Christophe PLAGNIOL-VILLARD * unprotect unprotects all locking. 121859829cc1SJean-Christophe PLAGNIOL-VILLARD */ 121959829cc1SJean-Christophe PLAGNIOL-VILLARD if ((prot == 0) && (info->legacy_unlock)) { 122059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_sect_t i; 122159829cc1SJean-Christophe PLAGNIOL-VILLARD 122259829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < info->sector_count; i++) { 122359829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->protect[i]) 122459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_real_protect (info, i, 1); 122559829cc1SJean-Christophe PLAGNIOL-VILLARD } 122659829cc1SJean-Christophe PLAGNIOL-VILLARD } 122759829cc1SJean-Christophe PLAGNIOL-VILLARD } 122859829cc1SJean-Christophe PLAGNIOL-VILLARD return retcode; 122959829cc1SJean-Christophe PLAGNIOL-VILLARD } 123059829cc1SJean-Christophe PLAGNIOL-VILLARD 123159829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 123259829cc1SJean-Christophe PLAGNIOL-VILLARD * flash_read_user_serial - read the OneTimeProgramming cells 123359829cc1SJean-Christophe PLAGNIOL-VILLARD */ 123459829cc1SJean-Christophe PLAGNIOL-VILLARD void flash_read_user_serial (flash_info_t * info, void *buffer, int offset, 123559829cc1SJean-Christophe PLAGNIOL-VILLARD int len) 123659829cc1SJean-Christophe PLAGNIOL-VILLARD { 123759829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *src; 123859829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *dst; 123959829cc1SJean-Christophe PLAGNIOL-VILLARD 124059829cc1SJean-Christophe PLAGNIOL-VILLARD dst = buffer; 124159829cc1SJean-Christophe PLAGNIOL-VILLARD src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION); 124259829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID); 124359829cc1SJean-Christophe PLAGNIOL-VILLARD memcpy (dst, src + offset, len); 124459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 124559829cc1SJean-Christophe PLAGNIOL-VILLARD } 124659829cc1SJean-Christophe PLAGNIOL-VILLARD 124759829cc1SJean-Christophe PLAGNIOL-VILLARD /* 124859829cc1SJean-Christophe PLAGNIOL-VILLARD * flash_read_factory_serial - read the device Id from the protection area 124959829cc1SJean-Christophe PLAGNIOL-VILLARD */ 125059829cc1SJean-Christophe PLAGNIOL-VILLARD void flash_read_factory_serial (flash_info_t * info, void *buffer, int offset, 125159829cc1SJean-Christophe PLAGNIOL-VILLARD int len) 125259829cc1SJean-Christophe PLAGNIOL-VILLARD { 125359829cc1SJean-Christophe PLAGNIOL-VILLARD uchar *src; 125459829cc1SJean-Christophe PLAGNIOL-VILLARD 125559829cc1SJean-Christophe PLAGNIOL-VILLARD src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION); 125659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID); 125759829cc1SJean-Christophe PLAGNIOL-VILLARD memcpy (buffer, src + offset, len); 125859829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 125959829cc1SJean-Christophe PLAGNIOL-VILLARD } 126059829cc1SJean-Christophe PLAGNIOL-VILLARD 126159829cc1SJean-Christophe PLAGNIOL-VILLARD #endif /* CFG_FLASH_PROTECTION */ 126259829cc1SJean-Christophe PLAGNIOL-VILLARD 126359829cc1SJean-Christophe PLAGNIOL-VILLARD 126459829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 126559829cc1SJean-Christophe PLAGNIOL-VILLARD * read jedec ids from device and set corresponding fields in info struct 126659829cc1SJean-Christophe PLAGNIOL-VILLARD * 126759829cc1SJean-Christophe PLAGNIOL-VILLARD * Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct 126859829cc1SJean-Christophe PLAGNIOL-VILLARD * 126959829cc1SJean-Christophe PLAGNIOL-VILLARD */ 127059829cc1SJean-Christophe PLAGNIOL-VILLARD static void flash_read_jedec_ids (flash_info_t * info) 127159829cc1SJean-Christophe PLAGNIOL-VILLARD { 127259829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id = 0; 127359829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id = 0; 127459829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 = 0; 127559829cc1SJean-Christophe PLAGNIOL-VILLARD 127659829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 127759829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 127859829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 127959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); 128059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, FLASH_CMD_READ_ID); 128159829cc1SJean-Christophe PLAGNIOL-VILLARD udelay(1000); /* some flash are slow to respond */ 128259829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id = flash_read_uchar (info, 128359829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_MANUFACTURER_ID); 128459829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id = flash_read_uchar (info, 128559829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID); 128659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, FLASH_CMD_RESET); 128759829cc1SJean-Christophe PLAGNIOL-VILLARD break; 128859829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 128959829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 129059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, AMD_CMD_RESET); 129159829cc1SJean-Christophe PLAGNIOL-VILLARD flash_unlock_seq(info, 0); 129281b20cccSMichael Schwingen flash_write_cmd(info, 0, info->addr_unlock1, FLASH_CMD_READ_ID); 129359829cc1SJean-Christophe PLAGNIOL-VILLARD udelay(1000); /* some flash are slow to respond */ 129459829cc1SJean-Christophe PLAGNIOL-VILLARD info->manufacturer_id = flash_read_uchar (info, 129559829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_MANUFACTURER_ID); 129659829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id = flash_read_uchar (info, 129759829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID); 129859829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->device_id == 0x7E) { 129959829cc1SJean-Christophe PLAGNIOL-VILLARD /* AMD 3-byte (expanded) device ids */ 130059829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 = flash_read_uchar (info, 130159829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID2); 130259829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 <<= 8; 130359829cc1SJean-Christophe PLAGNIOL-VILLARD info->device_id2 |= flash_read_uchar (info, 130459829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_DEVICE_ID3); 130559829cc1SJean-Christophe PLAGNIOL-VILLARD } 130659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd(info, 0, 0, AMD_CMD_RESET); 130759829cc1SJean-Christophe PLAGNIOL-VILLARD break; 130859829cc1SJean-Christophe PLAGNIOL-VILLARD default: 130959829cc1SJean-Christophe PLAGNIOL-VILLARD break; 131059829cc1SJean-Christophe PLAGNIOL-VILLARD } 131159829cc1SJean-Christophe PLAGNIOL-VILLARD } 131259829cc1SJean-Christophe PLAGNIOL-VILLARD 1313be60a902SHaavard Skinnemoen #ifdef CONFIG_FLASH_CFI_LEGACY 1314be60a902SHaavard Skinnemoen /*----------------------------------------------------------------------- 1315be60a902SHaavard Skinnemoen * Call board code to request info about non-CFI flash. 1316be60a902SHaavard Skinnemoen * board_flash_get_legacy needs to fill in at least: 1317be60a902SHaavard Skinnemoen * info->portwidth, info->chipwidth and info->interface for Jedec probing. 1318be60a902SHaavard Skinnemoen */ 1319be60a902SHaavard Skinnemoen static int flash_detect_legacy(ulong base, int banknum) 1320be60a902SHaavard Skinnemoen { 1321be60a902SHaavard Skinnemoen flash_info_t *info = &flash_info[banknum]; 1322be60a902SHaavard Skinnemoen 1323be60a902SHaavard Skinnemoen if (board_flash_get_legacy(base, banknum, info)) { 1324be60a902SHaavard Skinnemoen /* board code may have filled info completely. If not, we 1325be60a902SHaavard Skinnemoen use JEDEC ID probing. */ 1326be60a902SHaavard Skinnemoen if (!info->vendor) { 1327be60a902SHaavard Skinnemoen int modes[] = { 1328be60a902SHaavard Skinnemoen CFI_CMDSET_AMD_STANDARD, 1329be60a902SHaavard Skinnemoen CFI_CMDSET_INTEL_STANDARD 1330be60a902SHaavard Skinnemoen }; 1331be60a902SHaavard Skinnemoen int i; 1332be60a902SHaavard Skinnemoen 1333be60a902SHaavard Skinnemoen for (i = 0; i < sizeof(modes) / sizeof(modes[0]); i++) { 1334be60a902SHaavard Skinnemoen info->vendor = modes[i]; 1335be60a902SHaavard Skinnemoen info->start[0] = base; 1336be60a902SHaavard Skinnemoen if (info->portwidth == FLASH_CFI_8BIT 1337be60a902SHaavard Skinnemoen && info->interface == FLASH_CFI_X8X16) { 1338be60a902SHaavard Skinnemoen info->addr_unlock1 = 0x2AAA; 1339be60a902SHaavard Skinnemoen info->addr_unlock2 = 0x5555; 1340be60a902SHaavard Skinnemoen } else { 1341be60a902SHaavard Skinnemoen info->addr_unlock1 = 0x5555; 1342be60a902SHaavard Skinnemoen info->addr_unlock2 = 0x2AAA; 1343be60a902SHaavard Skinnemoen } 1344be60a902SHaavard Skinnemoen flash_read_jedec_ids(info); 1345be60a902SHaavard Skinnemoen debug("JEDEC PROBE: ID %x %x %x\n", 1346be60a902SHaavard Skinnemoen info->manufacturer_id, 1347be60a902SHaavard Skinnemoen info->device_id, 1348be60a902SHaavard Skinnemoen info->device_id2); 1349be60a902SHaavard Skinnemoen if (jedec_flash_match(info, base)) 1350be60a902SHaavard Skinnemoen break; 1351be60a902SHaavard Skinnemoen } 1352be60a902SHaavard Skinnemoen } 1353be60a902SHaavard Skinnemoen 1354be60a902SHaavard Skinnemoen switch(info->vendor) { 1355be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_STANDARD: 1356be60a902SHaavard Skinnemoen case CFI_CMDSET_INTEL_EXTENDED: 1357be60a902SHaavard Skinnemoen info->cmd_reset = FLASH_CMD_RESET; 1358be60a902SHaavard Skinnemoen break; 1359be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_STANDARD: 1360be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_EXTENDED: 1361be60a902SHaavard Skinnemoen case CFI_CMDSET_AMD_LEGACY: 1362be60a902SHaavard Skinnemoen info->cmd_reset = AMD_CMD_RESET; 1363be60a902SHaavard Skinnemoen break; 1364be60a902SHaavard Skinnemoen } 1365be60a902SHaavard Skinnemoen info->flash_id = FLASH_MAN_CFI; 1366be60a902SHaavard Skinnemoen return 1; 1367be60a902SHaavard Skinnemoen } 1368be60a902SHaavard Skinnemoen return 0; /* use CFI */ 1369be60a902SHaavard Skinnemoen } 1370be60a902SHaavard Skinnemoen #else 1371be60a902SHaavard Skinnemoen static inline int flash_detect_legacy(ulong base, int banknum) 1372be60a902SHaavard Skinnemoen { 1373be60a902SHaavard Skinnemoen return 0; /* use CFI */ 1374be60a902SHaavard Skinnemoen } 1375be60a902SHaavard Skinnemoen #endif 1376be60a902SHaavard Skinnemoen 137759829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 137859829cc1SJean-Christophe PLAGNIOL-VILLARD * detect if flash is compatible with the Common Flash Interface (CFI) 137959829cc1SJean-Christophe PLAGNIOL-VILLARD * http://www.jedec.org/download/search/jesd68.pdf 138059829cc1SJean-Christophe PLAGNIOL-VILLARD */ 13817e5b9b47SHaavard Skinnemoen static int __flash_detect_cfi (flash_info_t * info) 138259829cc1SJean-Christophe PLAGNIOL-VILLARD { 138359829cc1SJean-Christophe PLAGNIOL-VILLARD int cfi_offset; 138459829cc1SJean-Christophe PLAGNIOL-VILLARD 138559829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 13867e5b9b47SHaavard Skinnemoen for (cfi_offset=0; 13877e5b9b47SHaavard Skinnemoen cfi_offset < sizeof(flash_offset_cfi) / sizeof(uint); 13887e5b9b47SHaavard Skinnemoen cfi_offset++) { 13897e5b9b47SHaavard Skinnemoen flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], 13907e5b9b47SHaavard Skinnemoen FLASH_CMD_CFI); 139159829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') 139259829cc1SJean-Christophe PLAGNIOL-VILLARD && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') 139359829cc1SJean-Christophe PLAGNIOL-VILLARD && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) { 13947e5b9b47SHaavard Skinnemoen info->interface = flash_read_ushort (info, 0, 13957e5b9b47SHaavard Skinnemoen FLASH_OFFSET_INTERFACE); 139659829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_offset = flash_offset_cfi[cfi_offset]; 139759829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("device interface is %d\n", 139859829cc1SJean-Christophe PLAGNIOL-VILLARD info->interface); 139959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("found port %d chip %d ", 140059829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth, info->chipwidth); 140159829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("port %d bits chip %d bits\n", 140259829cc1SJean-Christophe PLAGNIOL-VILLARD info->portwidth << CFI_FLASH_SHIFT_WIDTH, 140359829cc1SJean-Christophe PLAGNIOL-VILLARD info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 140442026c9cSBartlomiej Sieka 140542026c9cSBartlomiej Sieka /* calculate command offsets as in the Linux driver */ 140642026c9cSBartlomiej Sieka info->addr_unlock1 = 0x555; 140742026c9cSBartlomiej Sieka info->addr_unlock2 = 0x2aa; 140842026c9cSBartlomiej Sieka 140942026c9cSBartlomiej Sieka /* 141042026c9cSBartlomiej Sieka * modify the unlock address if we are 141142026c9cSBartlomiej Sieka * in compatibility mode 141242026c9cSBartlomiej Sieka */ 141342026c9cSBartlomiej Sieka if ( /* x8/x16 in x8 mode */ 141442026c9cSBartlomiej Sieka ((info->chipwidth == FLASH_CFI_BY8) && 141542026c9cSBartlomiej Sieka (info->interface == FLASH_CFI_X8X16)) || 141642026c9cSBartlomiej Sieka /* x16/x32 in x16 mode */ 141742026c9cSBartlomiej Sieka ((info->chipwidth == FLASH_CFI_BY16) && 141842026c9cSBartlomiej Sieka (info->interface == FLASH_CFI_X16X32))) 141942026c9cSBartlomiej Sieka { 142042026c9cSBartlomiej Sieka info->addr_unlock1 = 0xaaa; 142142026c9cSBartlomiej Sieka info->addr_unlock2 = 0x555; 142242026c9cSBartlomiej Sieka } 142342026c9cSBartlomiej Sieka 142481b20cccSMichael Schwingen info->name = "CFI conformant"; 142559829cc1SJean-Christophe PLAGNIOL-VILLARD return 1; 142659829cc1SJean-Christophe PLAGNIOL-VILLARD } 142759829cc1SJean-Christophe PLAGNIOL-VILLARD } 14287e5b9b47SHaavard Skinnemoen 14297e5b9b47SHaavard Skinnemoen return 0; 143059829cc1SJean-Christophe PLAGNIOL-VILLARD } 14317e5b9b47SHaavard Skinnemoen 14327e5b9b47SHaavard Skinnemoen static int flash_detect_cfi (flash_info_t * info) 14337e5b9b47SHaavard Skinnemoen { 14347e5b9b47SHaavard Skinnemoen debug ("flash detect cfi\n"); 14357e5b9b47SHaavard Skinnemoen 14367e5b9b47SHaavard Skinnemoen for (info->portwidth = CFG_FLASH_CFI_WIDTH; 14377e5b9b47SHaavard Skinnemoen info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) { 14387e5b9b47SHaavard Skinnemoen for (info->chipwidth = FLASH_CFI_BY8; 14397e5b9b47SHaavard Skinnemoen info->chipwidth <= info->portwidth; 14407e5b9b47SHaavard Skinnemoen info->chipwidth <<= 1) 14417e5b9b47SHaavard Skinnemoen if (__flash_detect_cfi(info)) 14427e5b9b47SHaavard Skinnemoen return 1; 144359829cc1SJean-Christophe PLAGNIOL-VILLARD } 144459829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("not found\n"); 144559829cc1SJean-Christophe PLAGNIOL-VILLARD return 0; 144659829cc1SJean-Christophe PLAGNIOL-VILLARD } 144759829cc1SJean-Christophe PLAGNIOL-VILLARD 144859829cc1SJean-Christophe PLAGNIOL-VILLARD /* 144959829cc1SJean-Christophe PLAGNIOL-VILLARD * The following code cannot be run from FLASH! 145059829cc1SJean-Christophe PLAGNIOL-VILLARD * 145159829cc1SJean-Christophe PLAGNIOL-VILLARD */ 145259829cc1SJean-Christophe PLAGNIOL-VILLARD ulong flash_get_size (ulong base, int banknum) 145359829cc1SJean-Christophe PLAGNIOL-VILLARD { 145459829cc1SJean-Christophe PLAGNIOL-VILLARD flash_info_t *info = &flash_info[banknum]; 145559829cc1SJean-Christophe PLAGNIOL-VILLARD int i, j; 145659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_sect_t sect_cnt; 145759829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned long sector; 145859829cc1SJean-Christophe PLAGNIOL-VILLARD unsigned long tmp; 145959829cc1SJean-Christophe PLAGNIOL-VILLARD int size_ratio; 146059829cc1SJean-Christophe PLAGNIOL-VILLARD uchar num_erase_regions; 146159829cc1SJean-Christophe PLAGNIOL-VILLARD int erase_region_size; 146259829cc1SJean-Christophe PLAGNIOL-VILLARD int erase_region_count; 146359829cc1SJean-Christophe PLAGNIOL-VILLARD int geometry_reversed = 0; 146459829cc1SJean-Christophe PLAGNIOL-VILLARD 146559829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr = 0; 146659829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_version = 0; 146759829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_PROTECTION 146859829cc1SJean-Christophe PLAGNIOL-VILLARD info->legacy_unlock = 0; 146959829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 147059829cc1SJean-Christophe PLAGNIOL-VILLARD 147159829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[0] = base; 147259829cc1SJean-Christophe PLAGNIOL-VILLARD 147359829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_detect_cfi (info)) { 147459829cc1SJean-Christophe PLAGNIOL-VILLARD info->vendor = flash_read_ushort (info, 0, 147559829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_PRIMARY_VENDOR); 147659829cc1SJean-Christophe PLAGNIOL-VILLARD flash_read_jedec_ids (info); 147759829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI); 147859829cc1SJean-Christophe PLAGNIOL-VILLARD num_erase_regions = flash_read_uchar (info, 147959829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_NUM_ERASE_REGIONS); 148059829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr = flash_read_ushort (info, 0, 148159829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_EXT_QUERY_T_P_ADDR); 148259829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->ext_addr) { 148359829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_version = (ushort) flash_read_uchar (info, 148459829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr + 3) << 8; 148559829cc1SJean-Christophe PLAGNIOL-VILLARD info->cfi_version |= (ushort) flash_read_uchar (info, 148659829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr + 4); 148759829cc1SJean-Christophe PLAGNIOL-VILLARD } 148859829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG 148959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_printqry (info, 0); 149059829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 149159829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 149259829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 149359829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 149459829cc1SJean-Christophe PLAGNIOL-VILLARD default: 149559829cc1SJean-Christophe PLAGNIOL-VILLARD info->cmd_reset = FLASH_CMD_RESET; 149659829cc1SJean-Christophe PLAGNIOL-VILLARD #ifdef CFG_FLASH_PROTECTION 149759829cc1SJean-Christophe PLAGNIOL-VILLARD /* read legacy lock/unlock bit from intel flash */ 149859829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->ext_addr) { 149959829cc1SJean-Christophe PLAGNIOL-VILLARD info->legacy_unlock = flash_read_uchar (info, 150059829cc1SJean-Christophe PLAGNIOL-VILLARD info->ext_addr + 5) & 0x08; 150159829cc1SJean-Christophe PLAGNIOL-VILLARD } 150259829cc1SJean-Christophe PLAGNIOL-VILLARD #endif 150359829cc1SJean-Christophe PLAGNIOL-VILLARD break; 150459829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_STANDARD: 150559829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_AMD_EXTENDED: 150659829cc1SJean-Christophe PLAGNIOL-VILLARD info->cmd_reset = AMD_CMD_RESET; 150759829cc1SJean-Christophe PLAGNIOL-VILLARD /* check if flash geometry needs reversal */ 150859829cc1SJean-Christophe PLAGNIOL-VILLARD if (num_erase_regions <= 1) 150959829cc1SJean-Christophe PLAGNIOL-VILLARD break; 151059829cc1SJean-Christophe PLAGNIOL-VILLARD /* reverse geometry if top boot part */ 151159829cc1SJean-Christophe PLAGNIOL-VILLARD if (info->cfi_version < 0x3131) { 151259829cc1SJean-Christophe PLAGNIOL-VILLARD /* CFI < 1.1, try to guess from device id */ 151359829cc1SJean-Christophe PLAGNIOL-VILLARD if ((info->device_id & 0x80) != 0) { 151459829cc1SJean-Christophe PLAGNIOL-VILLARD geometry_reversed = 1; 151559829cc1SJean-Christophe PLAGNIOL-VILLARD } 151659829cc1SJean-Christophe PLAGNIOL-VILLARD break; 151759829cc1SJean-Christophe PLAGNIOL-VILLARD } 151859829cc1SJean-Christophe PLAGNIOL-VILLARD /* CFI >= 1.1, deduct from top/bottom flag */ 151959829cc1SJean-Christophe PLAGNIOL-VILLARD /* note: ext_addr is valid since cfi_version > 0 */ 152059829cc1SJean-Christophe PLAGNIOL-VILLARD if (flash_read_uchar(info, info->ext_addr + 0xf) == 3) { 152159829cc1SJean-Christophe PLAGNIOL-VILLARD geometry_reversed = 1; 152259829cc1SJean-Christophe PLAGNIOL-VILLARD } 152359829cc1SJean-Christophe PLAGNIOL-VILLARD break; 152459829cc1SJean-Christophe PLAGNIOL-VILLARD } 152559829cc1SJean-Christophe PLAGNIOL-VILLARD 152659829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("manufacturer is %d\n", info->vendor); 152759829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("manufacturer id is 0x%x\n", info->manufacturer_id); 152859829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("device id is 0x%x\n", info->device_id); 152959829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("device id2 is 0x%x\n", info->device_id2); 153059829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("cfi version is 0x%04x\n", info->cfi_version); 153159829cc1SJean-Christophe PLAGNIOL-VILLARD 153259829cc1SJean-Christophe PLAGNIOL-VILLARD size_ratio = info->portwidth / info->chipwidth; 153359829cc1SJean-Christophe PLAGNIOL-VILLARD /* if the chip is x8/x16 reduce the ratio by half */ 153459829cc1SJean-Christophe PLAGNIOL-VILLARD if ((info->interface == FLASH_CFI_X8X16) 153559829cc1SJean-Christophe PLAGNIOL-VILLARD && (info->chipwidth == FLASH_CFI_BY8)) { 153659829cc1SJean-Christophe PLAGNIOL-VILLARD size_ratio >>= 1; 153759829cc1SJean-Christophe PLAGNIOL-VILLARD } 153859829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("size_ratio %d port %d bits chip %d bits\n", 153959829cc1SJean-Christophe PLAGNIOL-VILLARD size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH, 154059829cc1SJean-Christophe PLAGNIOL-VILLARD info->chipwidth << CFI_FLASH_SHIFT_WIDTH); 154159829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("found %d erase regions\n", num_erase_regions); 154259829cc1SJean-Christophe PLAGNIOL-VILLARD sect_cnt = 0; 154359829cc1SJean-Christophe PLAGNIOL-VILLARD sector = base; 154459829cc1SJean-Christophe PLAGNIOL-VILLARD for (i = 0; i < num_erase_regions; i++) { 154559829cc1SJean-Christophe PLAGNIOL-VILLARD if (i > NUM_ERASE_REGIONS) { 154659829cc1SJean-Christophe PLAGNIOL-VILLARD printf ("%d erase regions found, only %d used\n", 154759829cc1SJean-Christophe PLAGNIOL-VILLARD num_erase_regions, NUM_ERASE_REGIONS); 154859829cc1SJean-Christophe PLAGNIOL-VILLARD break; 154959829cc1SJean-Christophe PLAGNIOL-VILLARD } 155059829cc1SJean-Christophe PLAGNIOL-VILLARD if (geometry_reversed) 155159829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = flash_read_long (info, 0, 155259829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_ERASE_REGIONS + 155359829cc1SJean-Christophe PLAGNIOL-VILLARD (num_erase_regions - 1 - i) * 4); 155459829cc1SJean-Christophe PLAGNIOL-VILLARD else 155559829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = flash_read_long (info, 0, 155659829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_ERASE_REGIONS + 155759829cc1SJean-Christophe PLAGNIOL-VILLARD i * 4); 155859829cc1SJean-Christophe PLAGNIOL-VILLARD erase_region_size = 155959829cc1SJean-Christophe PLAGNIOL-VILLARD (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128; 156059829cc1SJean-Christophe PLAGNIOL-VILLARD tmp >>= 16; 156159829cc1SJean-Christophe PLAGNIOL-VILLARD erase_region_count = (tmp & 0xffff) + 1; 156259829cc1SJean-Christophe PLAGNIOL-VILLARD debug ("erase_region_count = %d erase_region_size = %d\n", 156359829cc1SJean-Christophe PLAGNIOL-VILLARD erase_region_count, erase_region_size); 156459829cc1SJean-Christophe PLAGNIOL-VILLARD for (j = 0; j < erase_region_count; j++) { 156581b20cccSMichael Schwingen if (sect_cnt >= CFG_MAX_FLASH_SECT) { 156681b20cccSMichael Schwingen printf("ERROR: too many flash sectors\n"); 156781b20cccSMichael Schwingen break; 156881b20cccSMichael Schwingen } 156959829cc1SJean-Christophe PLAGNIOL-VILLARD info->start[sect_cnt] = sector; 157059829cc1SJean-Christophe PLAGNIOL-VILLARD sector += (erase_region_size * size_ratio); 157159829cc1SJean-Christophe PLAGNIOL-VILLARD 157259829cc1SJean-Christophe PLAGNIOL-VILLARD /* 15737e5b9b47SHaavard Skinnemoen * Only read protection status from 15747e5b9b47SHaavard Skinnemoen * supported devices (intel...) 157559829cc1SJean-Christophe PLAGNIOL-VILLARD */ 157659829cc1SJean-Christophe PLAGNIOL-VILLARD switch (info->vendor) { 157759829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_EXTENDED: 157859829cc1SJean-Christophe PLAGNIOL-VILLARD case CFI_CMDSET_INTEL_STANDARD: 157959829cc1SJean-Christophe PLAGNIOL-VILLARD info->protect[sect_cnt] = 158059829cc1SJean-Christophe PLAGNIOL-VILLARD flash_isset (info, sect_cnt, 158159829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_OFFSET_PROTECT, 158259829cc1SJean-Christophe PLAGNIOL-VILLARD FLASH_STATUS_PROTECT); 158359829cc1SJean-Christophe PLAGNIOL-VILLARD break; 158459829cc1SJean-Christophe PLAGNIOL-VILLARD default: 15857e5b9b47SHaavard Skinnemoen /* default: not protected */ 15867e5b9b47SHaavard Skinnemoen info->protect[sect_cnt] = 0; 158759829cc1SJean-Christophe PLAGNIOL-VILLARD } 158859829cc1SJean-Christophe PLAGNIOL-VILLARD 158959829cc1SJean-Christophe PLAGNIOL-VILLARD sect_cnt++; 159059829cc1SJean-Christophe PLAGNIOL-VILLARD } 159159829cc1SJean-Christophe PLAGNIOL-VILLARD } 159259829cc1SJean-Christophe PLAGNIOL-VILLARD 159359829cc1SJean-Christophe PLAGNIOL-VILLARD info->sector_count = sect_cnt; 15947e5b9b47SHaavard Skinnemoen info->size = 1 << flash_read_uchar (info, FLASH_OFFSET_SIZE); 159559829cc1SJean-Christophe PLAGNIOL-VILLARD /* multiply the size by the number of chips */ 15967e5b9b47SHaavard Skinnemoen info->size *= size_ratio; 15977e5b9b47SHaavard Skinnemoen info->buffer_size = 1 << flash_read_ushort (info, 0, 15987e5b9b47SHaavard Skinnemoen FLASH_OFFSET_BUFFER_SIZE); 159959829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = 1 << flash_read_uchar (info, FLASH_OFFSET_ETOUT); 16007e5b9b47SHaavard Skinnemoen info->erase_blk_tout = tmp * 16017e5b9b47SHaavard Skinnemoen (1 << flash_read_uchar ( 16027e5b9b47SHaavard Skinnemoen info, FLASH_OFFSET_EMAX_TOUT)); 160359829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WBTOUT)) * 160459829cc1SJean-Christophe PLAGNIOL-VILLARD (1 << flash_read_uchar (info, FLASH_OFFSET_WBMAX_TOUT)); 16057e5b9b47SHaavard Skinnemoen /* round up when converting to ms */ 16067e5b9b47SHaavard Skinnemoen info->buffer_write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); 160759829cc1SJean-Christophe PLAGNIOL-VILLARD tmp = (1 << flash_read_uchar (info, FLASH_OFFSET_WTOUT)) * 160859829cc1SJean-Christophe PLAGNIOL-VILLARD (1 << flash_read_uchar (info, FLASH_OFFSET_WMAX_TOUT)); 16097e5b9b47SHaavard Skinnemoen /* round up when converting to ms */ 16107e5b9b47SHaavard Skinnemoen info->write_tout = tmp / 1000 + (tmp % 1000 ? 1 : 0); 161159829cc1SJean-Christophe PLAGNIOL-VILLARD info->flash_id = FLASH_MAN_CFI; 16127e5b9b47SHaavard Skinnemoen if ((info->interface == FLASH_CFI_X8X16) && 16137e5b9b47SHaavard Skinnemoen (info->chipwidth == FLASH_CFI_BY8)) { 16147e5b9b47SHaavard Skinnemoen /* XXX - Need to test on x8/x16 in parallel. */ 16157e5b9b47SHaavard Skinnemoen info->portwidth >>= 1; 161659829cc1SJean-Christophe PLAGNIOL-VILLARD } 161759829cc1SJean-Christophe PLAGNIOL-VILLARD } 161859829cc1SJean-Christophe PLAGNIOL-VILLARD 161959829cc1SJean-Christophe PLAGNIOL-VILLARD flash_write_cmd (info, 0, 0, info->cmd_reset); 162059829cc1SJean-Christophe PLAGNIOL-VILLARD return (info->size); 162159829cc1SJean-Christophe PLAGNIOL-VILLARD } 162259829cc1SJean-Christophe PLAGNIOL-VILLARD 162359829cc1SJean-Christophe PLAGNIOL-VILLARD /*----------------------------------------------------------------------- 162459829cc1SJean-Christophe PLAGNIOL-VILLARD */ 1625be60a902SHaavard Skinnemoen unsigned long flash_init (void) 162659829cc1SJean-Christophe PLAGNIOL-VILLARD { 1627be60a902SHaavard Skinnemoen unsigned long size = 0; 1628be60a902SHaavard Skinnemoen int i; 162959829cc1SJean-Christophe PLAGNIOL-VILLARD 1630be60a902SHaavard Skinnemoen #ifdef CFG_FLASH_PROTECTION 1631be60a902SHaavard Skinnemoen char *s = getenv("unlock"); 163281b20cccSMichael Schwingen #endif 1633be60a902SHaavard Skinnemoen 1634be60a902SHaavard Skinnemoen /* Init: no FLASHes known */ 1635be60a902SHaavard Skinnemoen for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { 1636be60a902SHaavard Skinnemoen flash_info[i].flash_id = FLASH_UNKNOWN; 1637be60a902SHaavard Skinnemoen 1638be60a902SHaavard Skinnemoen if (!flash_detect_legacy (bank_base[i], i)) 1639be60a902SHaavard Skinnemoen flash_get_size (bank_base[i], i); 1640be60a902SHaavard Skinnemoen size += flash_info[i].size; 1641be60a902SHaavard Skinnemoen if (flash_info[i].flash_id == FLASH_UNKNOWN) { 1642be60a902SHaavard Skinnemoen #ifndef CFG_FLASH_QUIET_TEST 1643be60a902SHaavard Skinnemoen printf ("## Unknown FLASH on Bank %d " 1644be60a902SHaavard Skinnemoen "- Size = 0x%08lx = %ld MB\n", 1645be60a902SHaavard Skinnemoen i+1, flash_info[i].size, 1646be60a902SHaavard Skinnemoen flash_info[i].size << 20); 1647be60a902SHaavard Skinnemoen #endif /* CFG_FLASH_QUIET_TEST */ 164859829cc1SJean-Christophe PLAGNIOL-VILLARD } 1649be60a902SHaavard Skinnemoen #ifdef CFG_FLASH_PROTECTION 1650be60a902SHaavard Skinnemoen else if ((s != NULL) && (strcmp(s, "yes") == 0)) { 1651be60a902SHaavard Skinnemoen /* 1652be60a902SHaavard Skinnemoen * Only the U-Boot image and it's environment 1653be60a902SHaavard Skinnemoen * is protected, all other sectors are 1654be60a902SHaavard Skinnemoen * unprotected (unlocked) if flash hardware 1655be60a902SHaavard Skinnemoen * protection is used (CFG_FLASH_PROTECTION) 1656be60a902SHaavard Skinnemoen * and the environment variable "unlock" is 1657be60a902SHaavard Skinnemoen * set to "yes". 1658be60a902SHaavard Skinnemoen */ 1659be60a902SHaavard Skinnemoen if (flash_info[i].legacy_unlock) { 1660be60a902SHaavard Skinnemoen int k; 166159829cc1SJean-Christophe PLAGNIOL-VILLARD 1662be60a902SHaavard Skinnemoen /* 1663be60a902SHaavard Skinnemoen * Disable legacy_unlock temporarily, 1664be60a902SHaavard Skinnemoen * since flash_real_protect would 1665be60a902SHaavard Skinnemoen * relock all other sectors again 1666be60a902SHaavard Skinnemoen * otherwise. 1667be60a902SHaavard Skinnemoen */ 1668be60a902SHaavard Skinnemoen flash_info[i].legacy_unlock = 0; 166959829cc1SJean-Christophe PLAGNIOL-VILLARD 1670be60a902SHaavard Skinnemoen /* 1671be60a902SHaavard Skinnemoen * Legacy unlocking (e.g. Intel J3) -> 1672be60a902SHaavard Skinnemoen * unlock only one sector. This will 1673be60a902SHaavard Skinnemoen * unlock all sectors. 1674be60a902SHaavard Skinnemoen */ 1675be60a902SHaavard Skinnemoen flash_real_protect (&flash_info[i], 0, 0); 167659829cc1SJean-Christophe PLAGNIOL-VILLARD 1677be60a902SHaavard Skinnemoen flash_info[i].legacy_unlock = 1; 167859829cc1SJean-Christophe PLAGNIOL-VILLARD 1679be60a902SHaavard Skinnemoen /* 1680be60a902SHaavard Skinnemoen * Manually mark other sectors as 1681be60a902SHaavard Skinnemoen * unlocked (unprotected) 1682be60a902SHaavard Skinnemoen */ 1683be60a902SHaavard Skinnemoen for (k = 1; k < flash_info[i].sector_count; k++) 1684be60a902SHaavard Skinnemoen flash_info[i].protect[k] = 0; 1685be60a902SHaavard Skinnemoen } else { 1686be60a902SHaavard Skinnemoen /* 1687be60a902SHaavard Skinnemoen * No legancy unlocking -> unlock all sectors 1688be60a902SHaavard Skinnemoen */ 1689be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_CLEAR, 1690be60a902SHaavard Skinnemoen flash_info[i].start[0], 1691be60a902SHaavard Skinnemoen flash_info[i].start[0] 1692be60a902SHaavard Skinnemoen + flash_info[i].size - 1, 1693be60a902SHaavard Skinnemoen &flash_info[i]); 169459829cc1SJean-Christophe PLAGNIOL-VILLARD } 169559829cc1SJean-Christophe PLAGNIOL-VILLARD } 1696be60a902SHaavard Skinnemoen #endif /* CFG_FLASH_PROTECTION */ 169759829cc1SJean-Christophe PLAGNIOL-VILLARD } 169859829cc1SJean-Christophe PLAGNIOL-VILLARD 1699be60a902SHaavard Skinnemoen /* Monitor protection ON by default */ 1700be60a902SHaavard Skinnemoen #if (CFG_MONITOR_BASE >= CFG_FLASH_BASE) 1701be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_SET, 1702be60a902SHaavard Skinnemoen CFG_MONITOR_BASE, 1703be60a902SHaavard Skinnemoen CFG_MONITOR_BASE + monitor_flash_len - 1, 1704be60a902SHaavard Skinnemoen flash_get_info(CFG_MONITOR_BASE)); 1705be60a902SHaavard Skinnemoen #endif 170659829cc1SJean-Christophe PLAGNIOL-VILLARD 1707be60a902SHaavard Skinnemoen /* Environment protection ON by default */ 1708be60a902SHaavard Skinnemoen #ifdef CFG_ENV_IS_IN_FLASH 1709be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_SET, 1710be60a902SHaavard Skinnemoen CFG_ENV_ADDR, 1711be60a902SHaavard Skinnemoen CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, 1712be60a902SHaavard Skinnemoen flash_get_info(CFG_ENV_ADDR)); 1713be60a902SHaavard Skinnemoen #endif 1714be60a902SHaavard Skinnemoen 1715be60a902SHaavard Skinnemoen /* Redundant environment protection ON by default */ 1716be60a902SHaavard Skinnemoen #ifdef CFG_ENV_ADDR_REDUND 1717be60a902SHaavard Skinnemoen flash_protect (FLAG_PROTECT_SET, 1718be60a902SHaavard Skinnemoen CFG_ENV_ADDR_REDUND, 1719be60a902SHaavard Skinnemoen CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1, 1720be60a902SHaavard Skinnemoen flash_get_info(CFG_ENV_ADDR_REDUND)); 1721be60a902SHaavard Skinnemoen #endif 1722be60a902SHaavard Skinnemoen return (size); 172359829cc1SJean-Christophe PLAGNIOL-VILLARD } 172459829cc1SJean-Christophe PLAGNIOL-VILLARD 172559829cc1SJean-Christophe PLAGNIOL-VILLARD #endif /* CFG_FLASH_CFI */ 1726