📄 flash.c.svn-base
字号:
/* * (C) Copyright 2001 * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net * * (C) Copyright 2001 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <common.h>#include <environment.h>#include <linux/byteorder/swab.h>flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; // info for FLASH chips// Board support for 1 or 2 flash devices#define fwr16(addr, data) *(volatile ushort *)addr = (ushort)data#define frd16(addr) *(volatile ushort *)addr#define fwr32(addr, data) *(volatile ulong *)addr = (ulong)data#define frd32(addr) *(volatile ulong *)addr#define nGCS0_AMD 1#define READY 1#define ERR 2#define TMO 4int nGCS0_is_amd = nGCS0_AMD;/*----------------------------------------------------------------------- * Functions ------------------------------------------------------------------------*/void start_flash_info_print(flash_info_t *info);static ulong flash_get_size (void *addr, flash_info_t *info);static int write_data (flash_info_t *info, ulong dest, ulong data);static int intel_write_data (flash_info_t *info, ulong dest, ulong data);static int amd_write_data (flash_info_t *info, ulong dest, ushort data);static void flash_get_offsets (ulong base, flash_info_t *info);/*-----------------------------------------------------------------------*/unsigned long flash_init (void){ int i; ulong size = 0; for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { switch (i) { case 0: flash_get_size ((void *) PHYS_FLASH_1, &flash_info[i]); flash_get_offsets (PHYS_FLASH_1, &flash_info[i]); break; case 1:#if !CONFIG_NAND_BOOT if(nGCS0_is_amd == nGCS0_AMD){ flash_get_size ((void *) PHYS_FLASH_2, &flash_info[i]); flash_get_offsets (PHYS_FLASH_2, &flash_info[i]); }else{ flash_get_size ((void *) PHYS_FLASH_3, &flash_info[i]); flash_get_offsets (PHYS_FLASH_3, &flash_info[i]); }#else if(flash_get_size((void *) PHYS_FLASH_2, &flash_info[i]) != 0){ flash_get_offsets (PHYS_FLASH_2, &flash_info[i]); }else{ flash_get_size((void *) PHYS_FLASH_3, &flash_info[i]); flash_get_offsets (PHYS_FLASH_3, &flash_info[i]); }#endif break; default: panic ("configured too many flash banks!\n"); break; } size += flash_info[i].size; }// if(flash_get_size((void *) PHYS_FLASH_2, &flash_info[0]) != 0){// flash_get_offsets (PHYS_FLASH_2, &flash_info[0]);// }else{// flash_get_size((void *) PHYS_FLASH_3, &flash_info[0]);// flash_get_offsets (PHYS_FLASH_3, &flash_info[0]);// } // Protect monitor and environment sectors flash_protect ( FLAG_PROTECT_SET, CFG_FLASH_BASE, CFG_FLASH_BASE + monitor_flash_len - 1, &flash_info[0] ); if((flash_info[0].flash_id & FLASH_VENDMASK)== FLASH_MAN_AMD){ switch(flash_info[0].flash_id & FLASH_TYPEMASK){ case FLASH_AM400T: case FLASH_AM400B: case FLASH_AM800T: case FLASH_AM800B: flash_protect ( FLAG_PROTECT_SET, AMD_CFG_ENV_ADDR, AMD_CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] ); break; default: break; } }else if((flash_info[0].flash_id & FLASH_VENDMASK)== FLASH_MAN_INTEL){ switch(flash_info[0].flash_id & FLASH_TYPEMASK){ case FLASH_28F320J3A: case FLASH_28F640J3A: case FLASH_28F128J3A: flash_protect ( FLAG_PROTECT_SET, INTEL_CFG_ENV_ADDR, INTEL_CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0] ); break; default: break; } } for(i = 0; i < CFG_MAX_FLASH_BANKS; i++){ printf("Bank # %d => [",i); start_flash_info_print(&flash_info[i]); printf("]\n"); } return size;}/*-----------------------------------------------------------------------*/void start_flash_info_print(flash_info_t *info){ if (info->flash_id == FLASH_UNKNOWN) { printf ("missing or unknown FLASH type"); return; } switch (info->flash_id & FLASH_VENDMASK) { case FLASH_MAN_INTEL: if(info->base_addr == PHYS_FLASH_1) printf("<nGCS0:0x00000000> = "); else printf("<nGCS1:0x08000000> = "); printf("INTEL-"); break; case FLASH_MAN_AMD: if(info->base_addr == PHYS_FLASH_1) printf("<nGCS0:0x00000000> = "); else printf("<nGCS4:0x20000000> = "); printf("AMD-"); break; default: printf("Unknown Vendor "); break; } switch (info->flash_id & FLASH_TYPEMASK) { case FLASH_AM400T: printf("AM29LV400BT , %d KB", info->size>>10); break; case FLASH_AM400B: printf("AM29LV400BB , %d KB", info->size>>10); break; case FLASH_AM800T: printf("AM29LV800BT , %d KB", info->size>>10); break; case FLASH_AM800B: printf("AM29LV800BB , %d KB", info->size>>10); break; case FLASH_28F320J3A: printf("28F320J3A , %d MB", info->size>>20); break; case FLASH_28F640J3A: printf("28F640J3A , %d MB", info->size>>20); break; case FLASH_28F128J3A: printf("28F128J3A , %d MB", info->size>>20); break; default: printf("Unknown Chip Type"); break; } return;}/*-----------------------------------------------------------------------*/static void flash_get_offsets (ulong base, flash_info_t *info){ int i; if (info->flash_id == FLASH_UNKNOWN) { return; } if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) { switch(info->flash_id & FLASH_TYPEMASK){ case FLASH_AM400T: case FLASH_AM400B: case FLASH_AM800T: case FLASH_AM800B: for (i = 0; i < info->sector_count; i++) { if(i==0) info->start[i] = base; if(i==1) info->start[i] = base+0x4000; if(i==2) info->start[i] = base+0x6000; if(i==3) info->start[i] = base+0x8000; if(i>=4) info->start[i] = base + ((i-3) * AMD_FLASH_SECT_SIZE); info->protect[i] = 0; } break; default:// printf("Unknown AMD chip, chip ID = 0x%x\n", info->flash_id & FLASH_TYPEMASK); return; } }else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { switch(info->flash_id & FLASH_TYPEMASK){ case FLASH_28F320J3A: case FLASH_28F640J3A: case FLASH_28F128J3A: for (i = 0; i < info->sector_count; i++) { info->start[i] = base + (i * INTEL_FLASH_SECT_SIZE); info->protect[i] = 0; } break; default:// printf("Unknown INTEL chip, chip ID = 0x%x\n", info->flash_id & FLASH_TYPEMASK); return; } }}/*-----------------------------------------------------------------------*/void flash_print_info (flash_info_t *info){ int i; if (info->flash_id == FLASH_UNKNOWN) { printf ("missing or unknown FLASH type\n"); return; } switch (info->flash_id & FLASH_VENDMASK) { case FLASH_MAN_INTEL: printf ("INTEL "); break; case FLASH_MAN_AMD: printf("AMD "); break; default: printf ("Unknown Vendor "); break; } switch (info->flash_id & FLASH_TYPEMASK) { case FLASH_AM400T: printf("AM29LV400BT\n"); break; case FLASH_AM400B: printf("AM29LV400BB\n"); break; case FLASH_AM800T: printf("AM29LV800BT\n"); break; case FLASH_AM800B: printf("AM29LV800BB\n"); break; case FLASH_28F320J3A: printf("28F320J3A\n"); break; case FLASH_28F640J3A: printf("28F640J3A\n"); break; case FLASH_28F128J3A: printf ("28F128J3A\n"); break; default: printf ("Unknown Chip Type\n"); break; } printf (" Size: 0x%lx Bytes, %d Sectors\n", info->size , info->sector_count); printf (" Sector Start Addresses:"); for (i = 0; i < info->sector_count; ++i) { if ((i % 4) == 0) printf ("\n"); printf ("%08lX%s ", info->start[i], info->protect[i] ? "(RO)" : " "); } printf ("\n"); return;}/* The following code cannot be run from FLASH! */static ulong flash_get_size (void *base, flash_info_t *info){ volatile ushort value16; volatile ulong value32; ushort * addr16; ulong * addr32; addr16 = (ushort *)base; addr32 = (ulong *)base; addr16[0x555] = (ushort)0xaaaa; addr16[0x2aa] = (ushort)0x5555; addr16[0x555] = (ushort)0x9090; value16 = addr16[0]; switch(value16){ case (ushort)AMD_MANUFACT: info->flash_id = FLASH_MAN_AMD; info->base_addr = base; nGCS0_is_amd = nGCS0_AMD; value16 = addr16[1]; switch(value16){ case (ushort)AMD_ID_LV400T: //0x22B9 info->flash_id += FLASH_AM400T; info->sector_count = 11; info->size = 0x80000; break; case (ushort)AMD_ID_LV400B: //0x22BA info->flash_id += FLASH_AM400B; info->sector_count = 11; info->size = 0x80000; break; case (ushort)AMD_ID_LV800T: //0x22DA info->flash_id += FLASH_AM800T; info->sector_count = 19; info->size = 0x100000; break; case (ushort)AMD_ID_LV800B: // 0x225B info->flash_id += FLASH_AM800B; info->sector_count = 19; info->size = 0x100000; break; default: info->flash_id += FLASH_UNKNOWN; return 0; } addr16[0] = (ushort)0xf0f0; //AMD reset break; case (ushort)INTEL_MANUFACT: info->flash_id = FLASH_MAN_INTEL; info->base_addr = base; nGCS0_is_amd = 0; addr32[0x5555] = (ulong)0x00AA00AA; addr32[0x2AAA] = (ulong)0x00550055; addr32[0x5555] = (ulong)0x00900090; value32 = addr32[0]; value32 = addr32[1]; switch(value32){ case (ulong)INTEL_ID_28F320J3A: //0x160016 info->flash_id += FLASH_28F320J3A; info->sector_count = 32;//(0x400000/INTEL_FLASH_SECT_SIZE) * 2; info->size = 0x400000 * 2; break; case (ulong)INTEL_ID_28F640J3A: //0x170017 info->flash_id += FLASH_28F640J3A; info->sector_count = 64;//(0x800000/INTEL_FLASH_SECT_SIZE) * 2; info->size = 0x800000 * 2; break; case (ulong) INTEL_ID_28F128J3A: //0x180018 info->flash_id += FLASH_28F128J3A; info->sector_count = 128;//(0x1000000/INTEL_FLASH_SECT_SIZE) * 2; info->size = 0x1000000 * 2; break; default: info->flash_id = FLASH_UNKNOWN; return 0; } addr32[0] = (ulong)0x00ff00ff; break; default: info->flash_id = FLASH_UNKNOWN; info->sector_count = 0; info->size = 0; addr16[0] = (ushort)0xf0f0; // restore read mode addr32[0] = (ulong)0x00ff00ff; return 0; // no or unknown flash } if (info->sector_count > CFG_MAX_FLASH_SECT) {// printf ("** ERROR: sector count %d > max (%d) **\n",// info->sector_count, CFG_MAX_FLASH_SECT); info->sector_count = CFG_MAX_FLASH_SECT; } return (info->size);}/*-----------------------------------------------------------------------*/int flash_erase(flash_info_t *info, int s_first, int s_last){ switch(info->flash_id & FLASH_TYPEMASK) { case FLASH_AM400T: case FLASH_AM400B: case FLASH_AM800T: case FLASH_AM800B: return amd_flash_erase(info, s_first, s_last); case FLASH_28F320J3A: case FLASH_28F640J3A: case FLASH_28F128J3A: return intel_flash_erase(info, s_first, s_last); default: printf("erase error.. Unknown chip type\n"); break; } return 1;}int amd_flash_erase (flash_info_t *info, int s_first, int s_last){ ushort prot, sect, result; ulong base, chip; int rcode = 0; base = info->base_addr; if((s_first < 0) || (s_first > s_last)) { if(info->flash_id == FLASH_UNKNOWN) printf("- missing\n"); else printf("- no sectors to erase\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -