/*
* MTD map driver for AMD compatible flash chips (non-CFI)
*
* Author: Jonas Holmberg <jonas.holmberg@axis.com>
*
* $Id: amd_flash.c,v 1.1.1.1 2004/02/04 06:22:25 laputa Exp $
*
* Copyright (c) 2001 Axis Communications AB
*
* This file is under GPL.
*
*
* Author: Janghon Lyu <nandy@mizi.com>
*
* And then, I translated this file to the vivi.
*
*/
#include <config.h>
#include <printk.h>
#include <heap.h>
#include <time.h>
#include <mtd/map.h>
#include <mtd/mtd.h>
#include <mtd/flashchip.h>
#include <mtd/amd_flash.h>
#include <command.h>
#include <types.h>
#include <io.h>
#include <sizes.h>
#include <vivi_string.h>
#include <errno.h>
#include <string.h>
/* debugging macros */
#undef AMDFLASH_DEBUG
#ifdef AMDFLASH_DEBUG
#define DPRINTK(args...) printk(##args)
#else
#define DPRINTK(args...)
#endif
static const char im_name[] = "amd_flash";
static inline __u32 wide_read(struct map_info *map, __u32 addr)
{
if (map->buswidth == 1) {
return map->read8(map, addr);
} else if (map->buswidth == 2) {
return map->read16(map, addr);
} else if (map->buswidth == 4) {
return map->read32(map, addr);
}
return 0;
}
static inline void wide_write(struct map_info *map, __u32 val, __u32 addr)
{
if (map->buswidth == 1) {
map->write8(map, val, addr);
} else if (map->buswidth == 2) {
map->write16(map, val, addr);
} else if (map->buswidth == 4) {
map->write32(map, val, addr);
}
}
static inline __u32 make_cmd(struct map_info *map, __u32 cmd)
{
const struct amd_flash_private *private = map->fldrv_priv;
if ((private->interleave == 2) &&
(private->device_type == DEVICE_TYPE_X16)) {
cmd |= (cmd << 16);
}
return cmd;
}
static inline void send_unlock(struct map_info *map, unsigned long base)
{
wide_write(map, (CMD_UNLOCK_DATA_1 << 16) | CMD_UNLOCK_DATA_1,
base + (map->buswidth * ADDR_UNLOCK_1));
wide_write(map, (CMD_UNLOCK_DATA_2 << 16) | CMD_UNLOCK_DATA_2,
base + (map->buswidth * ADDR_UNLOCK_2));
}
static inline void send_cmd(struct map_info *map, unsigned long base, __u32 cmd)
{
send_unlock(map, base);
wide_write(map, make_cmd(map, cmd),
base + (map->buswidth * ADDR_UNLOCK_1));
}
static inline void send_cmd_to_addr(struct map_info *map, unsigned long base,
__u32 cmd, unsigned long addr)
{
send_unlock(map, base);
wide_write(map, make_cmd(map, cmd), addr);
}
static inline int flash_is_busy(struct map_info *map, unsigned long addr,
int interleave)
{
if ((interleave == 2) && (map->buswidth == 4)) {
__u32 read1, read2;
read1 = wide_read(map, addr);
read2 = wide_read(map, addr);
return (((read1 >> 16) & D6_MASK) !=
((read2 >> 16) & D6_MASK)) ||
(((read1 & 0xffff) & D6_MASK) !=
((read2 & 0xffff) & D6_MASK));
}
return ((wide_read(map, addr) & D6_MASK) !=
(wide_read(map, addr) & D6_MASK));
}
static inline void unlock_sector(struct map_info *map, unsigned long sect_addr,
int unlock)
{
/* Sector lock address. A6 = 1 for unlock, A6 = 0 for lock */
int SLA = unlock ?
(sect_addr | (0x40 * map->buswidth)) :
(sect_addr & ~(0x40 * map->buswidth)) ;
__u32 cmd = make_cmd(map, CMD_UNLOCK_SECTOR);
wide_write(map, make_cmd(map, CMD_RESET_DATA), 0);
wide_write(map, cmd, SLA); /* 1st cycle: write cmd to any address */
wide_write(map, cmd, SLA); /* 2nd cycle: write cmd to any address */
wide_write(map, cmd, SLA); /* 3rd cycle: write cmd to SLA */
}
static inline int is_sector_locked(struct map_info *map,
unsigned long sect_addr)
{
int status;
wide_write(map, CMD_RESET_DATA, 0);
send_cmd(map, sect_addr, CMD_MANUFACTURER_UNLOCK_DATA);
/* status is 0x0000 for unlocked and 0x0001 for locked */
status = wide_read(map, sect_addr + (map->buswidth * ADDR_SECTOR_LOCK));
wide_write(map, CMD_RESET_DATA, 0);
return status;
}
static int amd_flash_do_unlock(struct mtd_info *mtd, loff_t ofs, size_t len,
int is_unlock)
{
struct map_info *map;
struct mtd_erase_region_info *merip;
int eraseoffset, erasesize, eraseblocks;
int i;
int retval = 0;
int lock_status;
map = mtd->priv;
/* Pass the whole chip through sector by sector and check for each
sector if the sector and the given interval overlap */
for(i = 0; i < mtd->numeraseregions; i++) {
merip = &mtd->eraseregions[i];
eraseoffset = merip->offset;
erasesize = merip->erasesize;
eraseblocks = merip->numblocks;
if (ofs > eraseoffset + erasesize)
continue;
while (eraseblocks > 0) {
if (ofs < eraseoffset + erasesize && ofs + len > eraseoffset) {
unlock_sector(map, eraseoffset, is_unlock);
lock_status = is_sector_locked(map, eraseoffset);
if (is_unlock && lock_status) {
printk("Cannot unlock sector at address %x length %xx\n",
eraseoffset, merip->erasesize);
retval = -1;
} else if (!is_unlock && !lock_status) {
printk("Cannot lock sector at address %x length %x\n",
eraseoffset, merip->erasesize);
retval = -1;
}
}
eraseoffset += erasesize;
eraseblocks --;
}
}
return retval;
}
static int amd_flash_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
{
return amd_flash_do_unlock(mtd, ofs, len, 1);
}
static int amd_flash_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
{
return amd_flash_do_unlock(mtd, ofs, len, 0);
}
/*
* Reads JEDEC manufacturer ID and device ID and returns the index of the first
* matching table entry (-1 if not found or alias for already found chip).
*/
static int probe_new_chip(struct mtd_info *mtd, __u32 base,
struct flchip *chips,
struct amd_flash_private *private,
const struct amd_flash_info *table, int table_size)
{
__u32 mfr_id;
__u32 dev_id;
struct map_info *map = mtd->priv;
struct amd_flash_private temp;
int i;
temp.device_type = DEVICE_TYPE_X16; // Assume X16 (FIXME)
temp.interleave = 2;
map->fldrv_priv = &temp;
/* Enter autoselect mode. */
send_cmd(map, base, CMD_RESET_DATA);
send_cmd(map, base, CMD_MANUFACTURER_UNLOCK_DATA);
mfr_id = wide_read(map, base + (map->buswidth * ADDR_MANUFACTURER));
dev_id = wide_read(map, base + (map->buswidth * ADDR_DEVICE_ID));
if ((map->buswidth == 4) && ((mfr_id >> 16) == (mfr_id & 0xffff)) &&
((dev_id >> 16) == (dev_id & 0xffff))) {
mfr_id &= 0xffff;
dev_id &= 0xffff;
} else {
temp.interleave = 1;
}
for (i = 0; i < table_size; i++) {
if ((mfr_id == table[i].mfr_id) &&
(dev_id == table[i].dev_id)) {
if (chips) {
int j;
/* Is this an alias for an already found chip?
* In that case that chip should be in
* autoselect mode now.
*/
for (j = 0; j < private->numchips; j++) {
__u32 mfr_id_other;
__u32 dev_id_other;
mfr_id_other =
wide_read(map, chips[j].start +
(map->buswidth *
ADDR_MANUFACTURER
));
dev_id_other =
wide_read(map, chips[j].start +
(map->buswidth *
ADDR_DEVICE_ID));
if (temp.interleave == 2) {
mfr_id_other &= 0xffff;
dev_id_other &= 0xffff;
}
if ((mfr_id_other == mfr_id) &&
(dev_id_other == dev_id)) {
/* Exit autoselect mode. */
send_cmd(map, base,
CMD_RESET_DATA);
return -1;
}
}
if (private->numchips == MAX_AMD_CHIPS) {
printk("%s: Too many flash chips "
"detected. Increase "
"MAX_AMD_CHIPS from %d.\n",
map->name, MAX_AMD_CHIPS);
return -1;
}
chips[private->numchips].start = base;
private->numchips++;
}
printk("%s: Found %d x %ldMiB %s at 0x%x\n", map->name,
temp.interleave, (table[i].size)/(1024*1024),
table[i].name, base);
mtd->size += table[i].size * temp.interleave;
mtd->numeraseregions += table[i].numeraseregions;
break;
}
}
/* Exit autoselect mode. */
send_cmd(map, base, CMD_RESET_DATA);
if (i == table_size) {
printk("%s: unknown flash device at 0x%x, "
"mfr id 0x%x, dev id 0x%x\n", map->name,
base, mfr_id, d
没有合适的资源?快使用搜索试试~ 我知道了~
vivi_2440源码
共192个文件
h:78个
c:64个
makefile:14个
5星 · 超过95%的资源 需积分: 0 41 下载量 134 浏览量
2011-11-21
10:42:12
上传
评论
收藏 319KB ZIP 举报
温馨提示
vivi_2440源码vivi_2440源码vivi_2440源码vivi_2440源码vivi_2440源码vivi_2440源码vivi_2440源码
资源推荐
资源详情
资源评论
收起资源包目录
vivi_2440源码 (192个子文件)
amd_flash.c 28KB
smc_core_2440.c 27KB
smc_core.c 26KB
cfi_cmdset_0001.c 25KB
bootp.c 18KB
net.c 16KB
forte_ide.c 16KB
textbox.c 15KB
menubox.c 13KB
mtdcore.c 12KB
memory.c 11KB
memtst.c 11KB
boot_kernel.c 10KB
imagewrite.c 10KB
proc.c 10KB
util.c 10KB
bon.c 10KB
cfi_probe.c 10KB
checklist.c 10KB
printk.c 9KB
test.c 8KB
command.c 8KB
s3c2440_flash.c 8KB
ymodem.c 8KB
mtdpart.c 7KB
getcmd_ext.c 7KB
gen_probe.c 7KB
param.c 7KB
cs8900.c 6KB
tftp.c 6KB
inputbox.c 6KB
lxdialog.c 6KB
rw.c 6KB
mmu.c 5KB
nand_ecc.c 5KB
xmodem.c 5KB
load_file.c 5KB
misc.c 4KB
smdk2440_test.c 4KB
main.c 4KB
string.c 4KB
exec.c 3KB
ecc.c 3KB
yesno.c 3KB
heap.c 3KB
smdk.c 3KB
msgbox.c 2KB
smc_test.c 2KB
arp.c 2KB
time.c 2KB
rarp.c 2KB
nand_read.c 2KB
hello.c 2KB
ctype.c 1KB
term.c 1KB
serial_core.c 1KB
reset_handle.c 1KB
getcmd.c 1KB
net_device.c 1KB
chipreg.c 1007B
timer.c 410B
version.c 263B
call_func.c 251B
skeleton.c 163B
ChangeLog 905B
.config 2KB
Configure 12KB
COPYING 18KB
s3c2440.h 17KB
ide.h 14KB
smdk2440.h 12KB
cs8900.h 12KB
cfi.h 11KB
gill.h 8KB
enda.h 7KB
nand.h 6KB
exilien102.h 6KB
mtd.h 6KB
dialog.h 6KB
colors.h 5KB
smdk2410.h 4KB
sa1100_gen_memmap.h 4KB
s3c2410_gen_memmap.h 4KB
mport3.h 4KB
gamepark.h 4KB
nand_ids.h 3KB
cap.h 3KB
trizeps2.h 3KB
bitfield.h 3KB
amd_flash.h 3KB
map.h 3KB
ymodem.h 2KB
bootp.h 2KB
bootp.h 2KB
premium.h 2KB
autoconf.h 2KB
smdk2400.h 2KB
proc_s3c2440.h 2KB
pxa250_gen_memmap.h 2KB
sa1100_gen_memmapB.h 2KB
共 192 条
- 1
- 2
lb_cheng
- 粉丝: 1
- 资源: 12
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 877668389368492摩托车队经理.apk
- IDM下载器官网免安装包,注册CMD文件,突破30天的限制
- qud.win.1.1-installer-10053.9.zip
- adb-r-linux.zip adb-r-linux.zip
- 对光伏出力预测的优化设计,实现了部分功能(注释完全,可直接运行)(文档加Matlab源码)
- 70-android.rules
- 可用于光伏出力预测,引入气象影响因子,效果良好(注释完全,可直接运行)(文档加Matlab源码)
- 利用白噪声特性和ARMR模型,通过求解模型参数生成随机风速(注释完全,可直接运行)(文档加Matlab源码)
- 51-android.rules
- RecationTest.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
前往页