📄 flash.c.orig
字号:
/***************************************** Copyright (c) 2001-2002 Sigma Designs, Inc. All Rights Reserved Proprietary and Confidential *****************************************//* This file is part of the boot loader *//* * flash.c * * flash driver from scratch * following CFI (Common Flash Memory Interface) Specification 2.0 * support multiple flashes * * first revision by Ho Lee 10/31/2002 * code cleanup by Ho Lee 11/08/2002 */#include "config.h"#include "uart.h"#include "util.h"#include "specific.h"#include "io.h"#include "flash.h"#ifdef SUPPORT_FLASH/* * AM29LV160DB : 16 Mbit (0x200000) * buswidth : 2 (16 bits) * interleave : 1 * device type : 2 */#define CFIDEV_BUSWIDTH 2#define CFIDEV_INTERLEAVE 1#define CFIDEV_DEVTYPE 2//// for matching endian between CPU and CFI interface// CFI and HOST use same endian//#define cpu_to_cfi8(x) (x)#define cfi8_to_cpu(x) (x)#define cpu_to_cfi16(x) (x)#define cfi16_to_cpu(x) (x)#define cpu_to_cfi32(x) (x)#define cfi32_to_cpu(x) (x)//// address remapping// for JASPER, after remapping, 0x0000 - 0x2000 area of flash is mapped to 0x400000 - 0x402000//#define REMAPPED 0#if REMAPPED#define JFTL(x) (((x) < 0x2000) ? ((x) + 0x400000) : (x)) // after remapping#else#define JFTL(x) (x) // before remapping#endif//// CFI information type definitions//#define P_ID_NONE 0#define P_ID_INTEL_EXT 1#define P_ID_AMD_STD 2#define P_ID_INTEL_STD 3#define P_ID_AMD_EXT 4#define P_ID_MITSUBISHI_STD 256#define P_ID_MITSUBISHI_EXT 257#define P_ID_RESERVED 65535struct cfi_ident { unsigned char qry[3]; unsigned short P_ID; unsigned short P_ADR; unsigned short A_ID; unsigned short A_ADR; unsigned char VccMin; unsigned char VccMax; unsigned char VppMin; unsigned char VppMax; unsigned char WordWriteTimeoutTyp; unsigned char BufWriteTimeoutTyp; unsigned char BlockEraseTimeoutTyp; unsigned char ChipEraseTimeoutTyp; unsigned char WordWriteTimeoutMax; unsigned char BufWriteTimeoutMax; unsigned char BlockEraseTimeoutMax; unsigned char ChipEraseTimeoutMax; unsigned char DevSize; unsigned short InterfaceDesc; unsigned short MaxBufWriteSize; unsigned char NumEraseRegions; unsigned int EraseRegionInfo[FLASH_MAX_ERASE_REGIONS]; /* Not host ordered */} __attribute__((packed));struct cfi_eraseregions { unsigned int start; unsigned int size; unsigned int blocks;};typedef enum { FL_READY, FL_STATUS, FL_CFI_QUERY, FL_JEDEC_QUERY, FL_ERASING, FL_ERASE_SUSPENDING, FL_ERASE_SUSPENDED, FL_WRITING, FL_WRITING_TO_BUFFER, FL_WRITE_SUSPENDING, FL_WRITE_SUSPENDED, FL_PM_SUSPENDED, FL_SYNCING, FL_UNLOADING, FL_LOCKING, FL_UNLOCKING, FL_UNKNOWN} flstate_t;struct cfi_private { int exist; int chip_state; unsigned int base, size; struct cfi_ident ident; struct cfi_eraseregions erase_regions[FLASH_MAX_ERASE_REGIONS]; unsigned int addr_unlock1, addr_unlock2;};//// global variables//static int g_flash_inited = 0;static int g_flash_chips = 0;static struct cfi_private g_cfi[FLASH_MAX_CHIPSET];//// function prototypes//// data structure managementstatic struct cfi_private *get_free_cfi(void);static struct cfi_private *find_cfi(unsigned int addr);// CFI basic I/Ostatic __inline__ unsigned char cfi_read8(unsigned int addr) { return __raw_readb(JFTL(addr)); }static __inline__ unsigned short cfi_read16(unsigned int addr) { return __raw_readw(JFTL(addr)); }static __inline__ unsigned long cfi_read32(unsigned int addr) { return __raw_readl(JFTL(addr)); }static __inline__ void cfi_write8(unsigned int val, unsigned int addr) { __raw_writeb(val, addr); mb(); }static __inline__ void cfi_write16(unsigned int val, unsigned int addr) { __raw_writew(val, addr); mb(); }static __inline__ void cfi_write32(unsigned int val, unsigned int addr) { __raw_writel(val, addr); mb(); }// CFI advanced I/Ostatic __inline__ unsigned int cfi_build_cmd_addr(unsigned int cmd_ofs);static __inline__ unsigned int cfi_build_cmd(unsigned int cmd);static __inline__ void cfi_send_gen_cmd(unsigned int cmd, unsigned int cmd_addr, unsigned int base);// probing & setupstatic int cfi_probe_chip(struct cfi_private *pcfi);static int qry_present(unsigned int base);static int cfi_chip_setup(struct cfi_private *pcfi);static void cfi_cmdset_0002(struct cfi_private *pcfi);// init & basicint flash_found(void);int flash_init(unsigned int base, int force);// eraseint flash_erase_all(void);int flash_erase_oneblock(unsigned int addr);int flash_erase_region(unsigned int addr, unsigned int len);// writeint flash_write_onebyte(unsigned int addr, unsigned int data);int flash_write_oneword(unsigned int addr, unsigned int data);static int flash_write_data_internal(unsigned int addr, unsigned short *data, int nwords, struct cfi_private *pcfi);int flash_write_data(unsigned int addr, unsigned char *data, int len);// miscellaneousstatic char *cfi_vendorname(unsigned int vendor);void flash_list(void *vpcfi);int flash_calcblock(unsigned int addr, unsigned int *pstart, unsigned int *plen);//// data structure management// struct cfi_private *get_free_cfi(void){ int i; for (i = 0; i < FLASH_MAX_CHIPSET; ++i) if (!g_cfi[i].exist) return &g_cfi[i]; return NULL;}struct cfi_private *find_cfi(unsigned int addr){ int i; for (i = 0; i < FLASH_MAX_CHIPSET; ++i) if (g_cfi[i].exist) if (addr >= g_cfi[i].base && addr < g_cfi[i].base + g_cfi[i].size) return &g_cfi[i]; return NULL;}//// CFI basic I/O//__inline__ unsigned int cfi_read(addr){ switch (CFIDEV_BUSWIDTH) { case 1 : return cfi_read8(addr); case 2 : return cfi_read16(addr); case 4 : return cfi_read32(addr); default : return 0; }}__inline__ void cfi_write(unsigned val, unsigned int addr){ switch (CFIDEV_BUSWIDTH) { case 1 : cfi_write8(val, addr); break; case 2 : cfi_write16(val, addr); break; case 4 : cfi_write32(val, addr); break; default : break; }}// // CFI advanced I/O//__inline__ unsigned int cfi_build_cmd_addr(unsigned int cmd_ofs){ return cmd_ofs * CFIDEV_DEVTYPE * CFIDEV_INTERLEAVE;}__inline__ unsigned int cfi_build_cmd(unsigned int cmd){ unsigned int val = 0; switch (CFIDEV_BUSWIDTH) { case 1 : val = cmd; break; case 2 : if (CFIDEV_INTERLEAVE == 1) val = cpu_to_cfi16(cmd); else if (CFIDEV_INTERLEAVE == 2) val = cpu_to_cfi16((cmd << 8) | cmd); break; case 4 : if (CFIDEV_INTERLEAVE == 1) val = cpu_to_cfi32(cmd); else if (CFIDEV_INTERLEAVE == 2) val = cpu_to_cfi32((cmd << 16) | cmd); else if (CFIDEV_INTERLEAVE == 4) { val = (cmd << 16) | cmd; val = cpu_to_cfi32((val << 8) | val); } break; default : break; } return val;}__inline__ void cfi_send_gen_cmd(unsigned int cmd, unsigned int cmd_addr, unsigned int base){ cfi_write(cfi_build_cmd(cmd), base + cfi_build_cmd_addr(cmd_addr));}__inline__ void cfi_send_cmd(unsigned int cmd, unsigned int cmd_addr, unsigned int base){ cfi_write(cfi_build_cmd(cmd), base + cmd_addr);}//// probing & setup// int cfi_probe_chip(struct cfi_private *pcfi){ int ret; if (pcfi->exist) --g_flash_chips; pcfi->exist = 0; // Reset cfi_send_gen_cmd(0xf0, 0, pcfi->base); // Enter CFI Query mode cfi_send_gen_cmd(0x98, 0x55, pcfi->base); if ((ret = qry_present(pcfi->base)) != 0) return ret; pcfi->exist = 1; ++g_flash_chips; if ((ret = cfi_chip_setup(pcfi)) != 0) return ret; // Reset cfi_send_gen_cmd(0xf0, 0, pcfi->base); // internal settings cfi_cmdset_0002(pcfi); return FLASH_OK;}int qry_present(unsigned int base){ return (cfi_read(base + cfi_build_cmd_addr(0x10)) == cfi_build_cmd('Q') && cfi_read(base + cfi_build_cmd_addr(0x11)) == cfi_build_cmd('R') && cfi_read(base + cfi_build_cmd_addr(0x12)) == cfi_build_cmd('Y')) ? FLASH_OK : FLASH_NOTEXIST;}int cfi_chip_setup(struct cfi_private *pcfi){ int i; int num_erase_regions = cfi_read(pcfi->base + cfi_build_cmd_addr(0x2c)); unsigned int start; if (num_erase_regions == 0) return FLASH_NOREGION; for (i = 0; i < (sizeof pcfi->ident) - (sizeof pcfi->ident.EraseRegionInfo) + (num_erase_regions * 4); ++i) ((unsigned char *) &pcfi->ident)[i] = cfi_read(pcfi->base + cfi_build_cmd_addr(0x10 + i)); for (i = 0, start = 0; i < num_erase_regions; ++i) { pcfi->erase_regions[i].start = start; pcfi->erase_regions[i].size = 0x100 * ((pcfi->ident.EraseRegionInfo[i] >> 16) & 0xffff); pcfi->erase_regions[i].blocks = (pcfi->ident.EraseRegionInfo[i] & 0xffff) + 1; start += pcfi->erase_regions[i].size * pcfi->erase_regions[i].blocks; } pcfi->size = 1 << pcfi->ident.DevSize; return FLASH_OK;}void cfi_cmdset_0002(struct cfi_private *pcfi){ switch (CFIDEV_DEVTYPE) { case 1 : pcfi->addr_unlock1 = 0x555; pcfi->addr_unlock2 = 0x2aa; break; case 2 : pcfi->addr_unlock1 = 0xaaa; pcfi->addr_unlock2 = (CFIDEV_BUSWIDTH == CFIDEV_INTERLEAVE) ? 0x555 : 0x554; break; case 4 : pcfi->addr_unlock1 = 0x1555; pcfi->addr_unlock2 = 0xaaa; break; }}//// init & basic//int flash_found(void)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -