📄 dev_flash_intel.c
字号:
/*
dev_lcd_pxa.c - skyeye PXA25x serial lcd controllor simulation
Copyright (C) 2003 - 2005 Skyeye Develop Group
for help please send mail to <skyeye-developer@lists.gro.clinux.org>
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
*/
/*
* 09/22/2005 rewrite for new framework
* walimis
*
* ywc 2005-01-21 add for flash simulation
* core flash simulation source code from ipaqsim
* Thanks to ipaqsim's AUTHOR(s): Ye Wen (wenye@cs.ucsb.edu)
*/
#include <stdio.h>
#include "armdefs.h"
#include "dev_flash_intel.h"
#include "armmem.h"
/*ywc 2005-04-01*/
void init_querytable ();
static u32 query[INTEL_QUERYTABLE_SIZE]; /* query table */
/* return the lock bit */
#define ISLOCKED(x) (io->lock[(x)>>FLASH_SECTOR_SHIFT])
#define ADDR_SUSPENDED(x) \
((io->program_suspended && ((x) == io->program_latch_addr)) || \
(io->progbuf_suspended && (((x) >= io->pb_start) && ((x) < (io->pb_start+io->pb_count)))) || \
(io->erase_suspended && (((x) & FLASH_SECTOR_MASK) == (io->erase_latch_addr & FLASH_SECTOR_MASK))) )
#define DEVICE_SUSPENDED (io->program_suspended || io->progbuf_suspended || io->erase_suspended)
void
flash_intel_reset (struct device_desc *dev)
{
struct flash_device *flash_dev = (struct flash_device *) dev->dev;
struct flash_intel_io *io = (struct flash_intel_io *) dev->data;
unsigned int i;
io->size = INTEL28F128J3A_SIZE;
io->lock = malloc (io->size / FLASH_SECTOR_SIZE);
if (io->lock == NULL) {
printf ("\nflash memory lock allocation failed"); /* exit */
}
for (i = 0; i < io->size / FLASH_SECTOR_SIZE; i++) {
io->lock[i] = 0;
}
io->read_mode = WSM_READ_ARRAY;
io->wsm_mode = WSM_READY;
io->program_busy = io->progbuf_busy = io->erase_busy = io->lock_busy =
0;
io->program_suspended = io->progbuf_suspended = io->erase_suspended =
0;
io->protection_error = io->program_setlb_error =
io->erase_clearlb_error = io->program_volt_error = 0;
//io->vpen = 0; /* disable program/erase */
io->vpen = 1; /* enable program/erase */
io->pb_count = io->pb_loaded = 0;
init_querytable ();
}
static void
flash_intel_fini (struct device_desc *dev)
{
struct flash_intel_io *io = (struct flash_intel_io *) dev->data;
if (!dev->dev)
free (dev->dev);
if (!io)
free (io);
}
int
flash_intel_read_byte (struct device_desc *dev, u32 addr, u8 * data)
{
struct machine_config *mc = (struct machine_config *) dev->mach;
ARMul_State *state = (ARMul_State *) mc->state;
u32 temp, offset;
int ret = ADDR_HIT;
flash_intel_read_word (dev, addr, &temp);
offset = (((u32) state->bigendSig * 3) ^ (addr & 3)) << 3;
*data = (temp >> offset & 0xffL);
return ret;
}
int
flash_intel_read_halfword (struct device_desc *dev, u32 addr, u16 * data)
{
struct machine_config *mc = (struct machine_config *) dev->mach;
ARMul_State *state = (ARMul_State *) mc->state;
u32 temp, offset;
int ret = ADDR_HIT;
flash_intel_read_word (dev, addr, &temp);
offset = (((u32) state->bigendSig * 2) ^ (addr & 2)) << 3;
*data = (temp >> offset & 0xffffL);
return ret;
}
int
flash_intel_read_word (struct device_desc *dev, u32 addr, u32 * data)
{
struct flash_device *flash_dev = (struct flash_device *) dev->dev;
struct flash_intel_io *io = (struct flash_intel_io *) dev->data;
struct machine_config *mc = (struct machine_config *) dev->mach;
ARMul_State *state = (ARMul_State *) mc->state;
int ret = ADDR_HIT;
u32 temp;
switch (io->read_mode) {
case WSM_READ_ARRAY: /* read flash */
//data = mem[WORD_ADDR(addr)];
*data = real_read_word (state, addr);
//data = state->mem.rom[mbp - skyeye_config.mem.mem_banks][(addr- mbp->addr)>>2];
break;
case WSM_READ_ID: //read IDs
temp = WORD_ADDR (addr) & 0x00000001;
if (temp == 0) {
*data = BOTHCHIP (INTEL_MANUFACTURER_CODE);
} //manu. ID
else if (temp == 1) {
*data = BOTHCHIP (INTEL_28F128J3A_DEVICE_CODE);
} // device ID
else if (((addr & FLASH_SECTOR_OFF) >> WORD_SHIFT) == 2) //read lock state
*data = BOTHCHIP (ISLOCKED (addr) & 0x1);
else {
*data = 0;
printf ("\nFlash: read ID error: unknown address 0x%x\n", addr);
}
break;
case WSM_READ_STATUS: /* read status register */
/* first get the WSM busy/ready state */
temp = !io->program_busy && !io->progbuf_busy
&& !io->lock_busy && !io->erase_busy;
/* suppose no voltage error */
*data = BOTHCHIP ((temp << 7) |
(io->erase_suspended << 6) |
(io->erase_clearlb_error << 5) |
(io->program_setlb_error << 4) |
(io->program_volt_error << 3) |
(io->program_suspended << 2) | (io->
protection_error)
<< 1);
break;
case WSM_READ_QUERY: // read query table
//temp = WORD_ADDR(addr);
temp = WORD_ADDR (addr & 0x0000ffff);
*data = (temp < INTEL_QUERYTABLE_SIZE) ? query[temp] : 0;
break;
default:
printf ("\nFlash: invalid read mode: %d", io->read_mode);
*data = 0;
break;
}
return ret;
}
int
flash_intel_write_byte (struct device_desc *dev, u32 addr, u8 data)
{
int ret = ADDR_HIT;
printf ("\nFlash in current config does not support halfword write at 0x%x", addr);
return ret;
}
int
flash_intel_write_halfword (struct device_desc *dev, u32 addr, u16 data)
{
int ret = ADDR_HIT;
printf ("\nFlash in current config does not support byte write at 0x%x", addr);
return ret;
}
/* initialize a new WSM command sequence */
void
init_wsm (struct device_desc *dev, u32 addr, u32 data)
{
struct flash_intel_io *io = (struct flash_intel_io *) dev->data;
/* maybe we don't need to care the data symmetry */
//CHECK_DATA_VALID(data);
/*
* No timing support now, so Suspend/Resume has no effect
* July 1st, 2004 Ye Wen
*/
int i;
u32 cmd = data & 0xff;
switch (cmd) {
case WSM_READ_ARRAY:
io->read_mode = WSM_READ_ARRAY;
break;
case WSM_READ_ID:
io->read_mode = WSM_READ_ID;
break;
case WSM_READ_STATUS:
io->read_mode = WSM_READ_STATUS;
break;
case WSM_READ_QUERY:
io->read_mode = WSM_READ_QUERY;
break;
case WSM_CLEAR_STATUS:
io->protection_error = io->program_setlb_error =
io->erase_clearlb_error = io->program_volt_error = 0;
// is this right? I can't see it from spec.
// but the bootldr code implies this. Check
// program_flash_region in bootldr.c
// -July 28, 2004 Ye Wen
io->read_mode = WSM_READ_ARRAY;
break;
case WSM_PROGRAM:
case WSM_PROGRAM2:
io->wsm_mode = WSM_PROGRAM;
break;
case WSM_WRITE_BUFFER:
io->wsm_mode = WSM_WRITE_BUFFER;
io->read_mode = WSM_READ_STATUS;
io->pb_count = io->pb_loaded = 0;
for (i = 0; i < INTEL_WRITEBUFFER_SIZE; i++)
io->pb_buf[i] = 0xffffffff;
break;
case WSM_BLOCK_ERASE:
io->wsm_mode = WSM_BLOCK_ERASE;
break;
case WSM_SUSPEND:
if (io->program_busy)
io->program_suspended = 1;
else if (io->progbuf_busy)
io->progbuf_suspended = 1;
else if (io->erase_busy)
io->erase_suspended = 1;
else {
//ywc
//printf("\nFlash: nothing busy for suspending");
}
break;
case WSM_RESUME:
if (io->program_suspended)
io->program_suspended = 0;
else if (io->progbuf_suspended)
io->progbuf_suspended = 0;
else if (io->erase_suspended)
io->erase_suspended = 0;
else {
//ywc
//printf("\nFlash: nothing to resume");
}
break;
case WSM_LOCK_ACCESS:
io->wsm_mode = WSM_LOCK_ACCESS;
break;
case WSM_CONFIG:
case WSM_PROTECT:
printf ("\nFlash: command 0x%x not supported yet", cmd);
break;
default:
//ywc
//printf("\nFlash: command 0x%x unrecognized", cmd);
break;
}
}
int
flash_intel_write_word (struct device_desc *dev, u32 addr, u32 data)
{
struct machine_config *mc = (struct machine_config *) dev->mach;
struct flash_intel_io *io = (struct flash_intel_io *) dev->data;
ARMul_State *state = (ARMul_State *) mc->state;
unsigned int i;
int ret = ADDR_HIT;
u32 j;
//CHECK_ADDR_RANGE(addr);
switch (io->wsm_mode) {
case WSM_READY:
init_wsm (dev, addr, data);
break;
case WSM_WRITE_BUFFER:
if (io->pb_count == 0) { /* step 1: get count */
io->pb_count = (data & 0xff) + 1;
io->progbuf_latch_addr = addr;
if (io->pb_count > INTEL_WRITEBUFFER_SIZE) {
io->program_setlb_error =
io->erase_clearlb_error = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -