|
From: Erik M. <er...@us...> - 2001-10-21 21:35:14
|
Update of /cvsroot/blob/blob/src/blob
In directory usw-pr-cvs1:/tmp/cvs-serv16865
Added Files:
intel16.c intel32.c amd32.c nullflash.c
Log Message:
New flash functions per flash type
--- NEW FILE: intel16.c ---
/*
* intel16.c: Intel 16 bit flash driver
*
* Copyright (C) 2001 Erik Mouw (J.A...@it...)
* Copyright (C) 1999 Jan-Derk Bakker (J.D...@it...)
*
* 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: intel16.c,v 1.1 2001/10/21 21:35:11 erikm Exp $"
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/errno.h>
#include <blob/flash.h>
#include <blob/util.h>
/* flash commands for a single 16 bit intel flash chip */
#define READ_ARRAY 0x000000FF
#define ERASE_SETUP 0x00000020
#define ERASE_CONFIRM 0x000000D0
#define PGM_SETUP 0x00000040
#define STATUS_READ 0x00000070
#define STATUS_CLEAR 0x00000050
#define STATUS_BUSY 0x00000080
#define STATUS_ERASE_ERR 0x00000020
#define STATUS_PGM_ERR 0x00000010
static int do_erase(u16 *addr)
{
u16 result;
/* prepare for erase */
*addr = ERASE_SETUP;
barrier();
/* erase block */
*addr = ERASE_CONFIRM;
barrier();
/* status check */
do {
*addr = STATUS_READ;
barrier();
result = *addr;
barrier();
} while((~result & STATUS_BUSY) != 0);
/* put flash back into Read Array mode */
*addr = READ_ARRAY;
barrier();
if((result & STATUS_ERASE_ERR) != 0)
return -EFLASHERASE;
return 0;
}
static int do_write(u16 *dst, const u16* src)
{
u16 result;
/* setup flash for writing */
*dst = PGM_SETUP;
barrier();
/* write data */
*dst = *src;
barrier();
/* status check */
do {
*dst = STATUS_READ;
barrier();
result = *dst;
barrier();
} while((~result & STATUS_BUSY) != 0);
/* put flash back into Read Array mode */
*dst = READ_ARRAY;
barrier();
if(((result & STATUS_PGM_ERR) != 0) || (*dst != *src))
return -EFLASHPGM;
return 0;
}
/* erases a flash block at the given address */
/* we have to break this up in two erases at 16 bit aligned addresses
* (if necessary)
*/
static int flash_erase_intel16(u32 *addr)
{
int result;
u16 *addr16 = (u16*)addr;
/* erase first block */
result = do_erase(addr16);
if(result != 0)
return result;
addr16++;
/* if the second address is not erased, also erase it */
if(*addr16 != 0xffff)
result = do_erase(addr16);
if(result != 0)
return result;
return 0;
}
/* write a flash block at a given location */
/* this has to be broken up into two consectutive 16 bit writes */
static int flash_write_intel16(u32 *dst, const u32* src)
{
u16 *dst16 = (u16 *)dst;
u16 *src16 = (u16 *)src;
int result;
result = do_write(dst16, src16);
if(result != 0)
return result;
dst16++;
src16++;
result = do_write(dst16, src16);
if(result != 0)
return result;
return 0;
}
/* flash driver structure */
flash_driver_t intel16_flash_driver = {
flash_erase: flash_erase_intel16,
flash_write: flash_write_intel16,
};
--- NEW FILE: intel32.c ---
/*
* intel32.c: Intel 32 bit (2x 16 bit) flash driver
*
* Copyright (C) 2001 Erik Mouw (J.A...@it...)
* Copyright (C) 1999 Jan-Derk Bakker (J.D...@it...)
*
* 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: intel32.c,v 1.1 2001/10/21 21:35:11 erikm Exp $"
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/errno.h>
#include <blob/flash.h>
#include <blob/util.h>
/* flash commands for two 16 bit intel flash chips */
#define READ_ARRAY 0x00FF00FF
#define ERASE_SETUP 0x00200020
#define ERASE_CONFIRM 0x00D000D0
#define PGM_SETUP 0x00400040
#define STATUS_READ 0x00700070
#define STATUS_CLEAR 0x00500050
#define STATUS_BUSY 0x00800080
#define STATUS_ERASE_ERR 0x00200020
#define STATUS_PGM_ERR 0x00100010
/* erases a flash block at the given address */
static int flash_erase_intel32(u32 *addr)
{
u32 result;
/* prepare for erase */
*addr = data_to_flash(ERASE_SETUP);
barrier();
/* erase block */
*addr = data_to_flash(ERASE_CONFIRM);
barrier();
/* status check */
do {
*addr = data_to_flash(STATUS_READ);
barrier();
result = data_from_flash(*addr);
barrier();
} while((~result & STATUS_BUSY) != 0);
/* put flash back into Read Array mode */
*addr = data_to_flash(READ_ARRAY);
barrier();
if((result & STATUS_ERASE_ERR) != 0)
return -EFLASHERASE;
return 0;
}
/* write a flash block at a given location */
static int flash_write_intel32(u32 *dst, const u32* src)
{
u32 result;
/* setup flash for writing */
*dst = data_to_flash(PGM_SETUP);
barrier();
/* write data */
*dst = *src;
barrier();
/* status check */
do {
*dst = data_to_flash(STATUS_READ);
barrier();
result = data_from_flash(*dst);
barrier();
} while((~result & STATUS_BUSY) != 0);
/* put flash back into Read Array mode */
*dst = data_to_flash(READ_ARRAY);
barrier();
if(((result & STATUS_PGM_ERR) != 0) || (*dst != *src))
return -EFLASHPGM;
return 0;
}
/* flash driver structure */
flash_driver_t intel32_flash_driver = {
flash_erase: flash_erase_intel32,
flash_write: flash_write_intel32,
};
--- NEW FILE: amd32.c ---
/*
* amd32.c: AMD 32 bit (2x 16 bit) flash driver
*
* Copyright (C) 2001 Erik Mouw (J.A...@it...)
* Copyright (C) 2001 Russ Dill (Rus...@as...)
*
* 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.1 2001/10/21 21:35:11 erikm Exp $"
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/errno.h>
#include <blob/flash.h>
#include <blob/util.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
#warning "Please check AMD flash code"
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;
}
/* flash driver structure */
flash_driver_t amd32_flash_driver = {
flash_erase: flash_erase_amd32,
flash_write: flash_write_amd32,
};
--- NEW FILE: nullflash.c ---
/*
* nullflash.c: NULL flash driver
*
* Copyright (C) 2001 Erik Mouw (J.A...@it...)
*
* 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: nullflash.c,v 1.1 2001/10/21 21:35:11 erikm Exp $"
#ifdef HAVE_CONFIG_H
# include <blob/config.h>
#endif
#include <blob/errno.h>
#include <blob/flash.h>
#include <blob/util.h>
static int flash_erase_null(u32 *addr)
{
#ifdef BLOB_DEBUG
printerrprefix();
SerialOutputString("No flash_erase() function\n");
#endif
return -EFLASHERASE;
}
static int flash_write_null(u32 *dst, const u32* src)
{
#ifdef BLOB_DEBUG
printerrprefix();
SerialOutputString("No flash_write() function\n");
#endif
return -EFLASHPGM;
}
/* flash driver structure */
flash_driver_t null_flash_driver = {
flash_erase: flash_erase_null,
flash_write: flash_write_null,
};
|