📄 amd32.c
字号:
/*
* amd32.c: AMD 32 bit (2x 16 bit) flash driver
*
* Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
* Copyright (C) 2001 Russ Dill (Russ.Dill@asu.edu)
*
* 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
*
*/
#ident "$Id: amd32.c,v 1.4 2002/01/02 01:23:18 erikm Exp $"
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/errno.h>
#include <blob/flash.h>
#include <blob/util.h>
#include <blob/serial.h>
/* flash commands for two 16 bit AMD flash chips */
#define READ_ARRAY 0x00F000F0
#define UNLOCK1 0x00AA00AA
#define UNLOCK2 0x00550055
#define ERASE_SETUP 0x00800080
#define ERASE_CONFIRM 0x00300030
#define PGM_SETUP 0x00A000A0
#define UNLOCK_BYPASS 0x00200020
#define FLASH_ADDR1 (0x00000555 << 2)
#define FLASH_ADDR2 (0x000002AA << 2)
#define ERASE_DONE 0x00800080
#define RDY_MASK 0x00800080
#define STATUS_PGM_ERR 0x00200020
#define STATUS_ERASE_ERR 0x00000001
#define READY 1
#define ERR 2
static int flash_erase_amd32(u32 *addr)
{
u32 result;
int chip1, chip2;
/* prepare for erase */
*(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1);
barrier();
*(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2);
barrier();
*(u32 *)FLASH_ADDR1 = data_to_flash(ERASE_SETUP);
barrier();
/* erase command */
*(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1);
barrier();
*(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2);
barrier();
*addr = data_to_flash(ERASE_CONFIRM);
/* I just can't find clean ways of dealing with this flash...
* The error bit is a *set* bit, so if its read, and bit 7 is 0,
* but bit 5 is 1, its an error, however, after these status reads
* are done, erased flash goes to 0xff...sooo...each chip has to
* be caught where the bits are the status bits -- Russ */
/* Russ, why don't you do this like the LART does? Just check
* the status of chips with a single compare. -- Erik */
chip1 = chip2 = 0;
do {
result = data_from_flash(*addr);
barrier();
if (!chip1 && (result & 0xFFFF) & ERASE_DONE)
chip1 = READY;
if (!chip1 && (result & 0xFFFF) & STATUS_PGM_ERR)
chip1 = ERR;
if (!chip2 && (result >> 16) & ERASE_DONE)
chip2 = READY;
if (!chip2 && (result >> 16) & STATUS_PGM_ERR)
chip2 = ERR;
} while(!chip1 || !chip2);
/* put flash back into Read Array mode */
*(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY);
barrier();
if (chip1 == ERR || chip2 == ERR)
return -EFLASHERASE;
return 0;
}
static int flash_write_amd32(u32 *dst, const u32* src)
{
u32 result;
int chip1, chip2;
*(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK1);
barrier();
*(u32 *)FLASH_ADDR2 = data_to_flash(UNLOCK2);
barrier();
*(u32 *)FLASH_ADDR1 = data_to_flash(UNLOCK_BYPASS);
barrier();
*dst = data_to_flash(PGM_SETUP);
barrier();
*dst = *src;
barrier();
/* This is a pretty similar situation to the erasing status below
* Bit 7 is ~(data bit 7) until the flash is complete. If bit 5
* gets set before this happens, there is an error, but this could
* happen near the clock edge, and bit 5 could be the actual data
* before bit 7 changes, so we have to read again. -- Russ
*/
chip1 = chip2 = 0;
do {
result = data_from_flash(*dst);
barrier();
if (!chip1 && ((result & 0x80) == (*src & 0x80)))
chip1 = READY;
if (!chip1 && ((result & 0xFFFF) & STATUS_PGM_ERR)) {
result = data_from_flash(*dst);
barrier();
if ((result & 0x80) == (*src & 0x80))
chip1 = READY;
else
chip1 = ERR;
}
if (!chip2 && ((result & (0x80 << 16)) == (*src & (0x80 << 16))))
chip2 = READY;
if (!chip2 && ((result >> 16) & STATUS_PGM_ERR)) {
result = data_from_flash(*dst);
barrier();
if ((result & (0x80 << 16)) == (*src & (0x80 << 16)))
chip2 = READY;
else
chip2 = ERR;
}
} while (!chip1 || !chip2);
*(u32 *)FLASH_ADDR1 = data_to_flash(READ_ARRAY);
barrier();
if (chip1 == ERR || chip2 == ERR || *dst != *src)
return -EFLASHPGM;
return 0;
}
static int flash_lock_block_amd32(u32 *blockStart)
{
/* FIXME: if AMD flash can be locked, this function should be
* fleshed out -- Erik
*/
return 0;
}
static int flash_unlock_block_amd32(u32 *blockStart)
{
/* FIXME: if AMD flash can be unlocked, this function should
* be fleshed out -- Erik
*/
return 0;
}
static int flash_query_block_lock_amd32(u32 *blockStart)
{
/* FIXME: if AMD flash can be queried, this function should be
* fleshed out -- Erik
*/
return 0;
}
/* flash driver structure */
flash_driver_t amd32_flash_driver = {
erase: flash_erase_amd32,
write: flash_write_amd32,
lock_block: flash_lock_block_amd32,
unlock_block: flash_unlock_block_amd32,
query_block_lock: flash_query_block_lock_amd32
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -