2003-02-16 Marcel Telka <marcel@telka.sk>
* src/Makefile.am (jtag_SOURCES): Added new flash files with flash driver framework (August Hörandl). * src/flash-amd.c: New file with AMD flash support (August Hörandl). * src/flash-intel.c: New file. Extracted Intel flash support from src/flash.c file (August Hörandl, me). * src/flash.c (set_flash_driver): New function. Added support for flash drivers (August Hörandl). (flashceck): Ditto. (flashmsbin): Added support for flash driver (August Hörandl). (flashmem): Ditto. (flash_erase_block): Function moved to src/flash-intel.c (August Hörandl). (flash_unlock_block): Ditto. (flash_program): Ditto. (flash_erase_block32): Ditto. (flash_unlock_block32): Ditto. (flash_program32): Ditto. * src/flash.h: New file. Interface for flash drivers (August Hörandl). * src/help.c (help): Added list of supported flash drivers for 'flashmem' command (August Hörandl). * src/readmem.c (detectflash): Removed Intel specific code. Enhanced output messages (August Hörandl). git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@356 b68d4a1b-bc3d-0410-92ed-d4ac073336b7master
parent
e08ddfcd7d
commit
b7738d12bf
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Flash driver for AMD Am29LV640D, Am29LV641D, Am29LV642D
|
||||
* Copyright (C) 2003 AH
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by August Hörandl <august.hoerandl@gmx.at>
|
||||
*
|
||||
* Documentation:
|
||||
* [1] Advanced Micro Devices, "Am29LV640D/Am29LV641D",
|
||||
* September 20, 2002 Rev B, 22366b8.pdf
|
||||
* [2] Advanced Micro Devices, "Am29LV642D",
|
||||
* August 14, 2001 Rev A, 25022.pdf
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <flash/cfi.h>
|
||||
#include <flash/intel.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
static int dbg = 0;
|
||||
|
||||
static int amd_flash_erase_block( parts *ps, uint32_t adr );
|
||||
static int amd_flash_unlock_block( parts *ps, uint32_t adr );
|
||||
static int amd_flash_program( parts *ps, uint32_t adr, uint32_t data );
|
||||
static void amd_flash_read_array( parts *ps);
|
||||
|
||||
/* autodetect, we can handle this chip */
|
||||
static int
|
||||
amd_flash_autodetect( parts *ps, cfi_query_structure_t *cfi )
|
||||
{
|
||||
return (cfi->identification_string.pri_id_code == CFI_VENDOR_AMD_SCS);
|
||||
}
|
||||
|
||||
/*
|
||||
* check device status
|
||||
* 1/true PASS
|
||||
* 0/false FAIL
|
||||
*/
|
||||
/*
|
||||
* first implementation: see [1], page 29
|
||||
*/
|
||||
static int
|
||||
amdstatus29( parts *ps, uint32_t adr, uint32_t data )
|
||||
{
|
||||
int o = 2;
|
||||
int timeout;
|
||||
uint32_t dq7mask = ((1 << 7) << 16) + (1 << 7);
|
||||
uint32_t dq5mask = ((1 << 5) << 16) + (1 << 5);
|
||||
uint32_t bit7 = (data & (1 << 7)) != 0;
|
||||
uint32_t data1;
|
||||
|
||||
for (timeout = 0; timeout < 100; timeout++) {
|
||||
data1 = bus_read( ps, adr << o );
|
||||
data1 = bus_read( ps, adr << o );
|
||||
if (dbg)
|
||||
printf( "amdstatus %d: %04X (%04X) = %04X\n", timeout, data1, (data1 & dq7mask), bit7 );
|
||||
if (((data1 & dq7mask) == dq7mask) == bit7) /* FIXME: This looks non-portable */
|
||||
return 1;
|
||||
|
||||
if ((data1 & dq5mask) == dq5mask)
|
||||
break;
|
||||
usleep( 100 );
|
||||
}
|
||||
|
||||
data1 = bus_read( ps, adr << o );
|
||||
if (((data1 & dq7mask) == dq7mask) == bit7) /* FIXME: This looks non-portable */
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* second implementation: see [1], page 30
|
||||
*/
|
||||
static int
|
||||
amdstatus( parts *ps, uint32_t adr, int data )
|
||||
{
|
||||
int timeout;
|
||||
uint32_t togglemask = ((1 << 6) << 16) + (1 << 6); /* DQ 6 */
|
||||
/* int dq5mask = ((1 << 5) << 16) + (1 << 5); DQ5 */
|
||||
|
||||
for (timeout = 0; timeout < 100; timeout++) {
|
||||
uint32_t data1 = bus_read( ps, adr );
|
||||
uint32_t data2 = bus_read( ps, adr );
|
||||
|
||||
/*printf("amdstatus %d: %04X/%04X %04X/%04X \n", */
|
||||
/* timeout, data1, data2, (data1 & togglemask), (data2 & togglemask)); */
|
||||
if ( (data1 & togglemask) == (data2 & togglemask)) /* no toggle */
|
||||
return 1;
|
||||
|
||||
/* if ( (data1 & dq5mask) != 0 ) TODO */
|
||||
/* return 0; */
|
||||
if (dbg)
|
||||
printf( "amdstatus %d: %04X/%04X\n", timeout, data1, data2 );
|
||||
else
|
||||
printf( "." );
|
||||
usleep( 100 );
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
amdisprotected( parts *ps, uint32_t adr )
|
||||
{
|
||||
uint32_t data;
|
||||
int o = 2;
|
||||
|
||||
bus_write( ps, 0x0555 << o, 0x00aa00aa ); /* autoselect p29, sector erase */
|
||||
bus_write( ps, 0x02aa << o, 0x00550055 );
|
||||
bus_write( ps, 0x0555 << o, 0x00900090 );
|
||||
|
||||
data = bus_read( ps, adr + (0x0002 << 2) );
|
||||
/* Read Array */
|
||||
amd_flash_read_array( ps ); /* AMD reset */
|
||||
|
||||
return ((data & 0x00ff00ff) != 0);
|
||||
}
|
||||
|
||||
static void
|
||||
amd_flash_print_info( parts *ps )
|
||||
{
|
||||
int o = 2;
|
||||
int mid, cid, prot;
|
||||
bus_write( ps, 0x0555 << o, 0x00aa00aa ); /* autoselect p29 */
|
||||
bus_write( ps, 0x02aa << o, 0x00550055 );
|
||||
bus_write( ps, 0x0555 << o, 0x00900090 );
|
||||
mid = bus_read( ps, 0x00 << o ) & 0xFFFF;
|
||||
cid = bus_read( ps, 0x01 << o ) & 0xFFFF;
|
||||
prot = bus_read( ps, 0x02 << o ) & 0xFF;
|
||||
amd_flash_read_array(ps); /* AMD reset */
|
||||
printf( "Chip: AMD Flash\n\tManufacturer: " );
|
||||
switch (mid) {
|
||||
case 0x0001:
|
||||
printf( "AMD" );
|
||||
break;
|
||||
default:
|
||||
printf( "Unknown manufacturer (ID 0x%04x)", mid );
|
||||
break;
|
||||
}
|
||||
printf( "\n\tChip: " );
|
||||
switch (cid) {
|
||||
case 0x22D7:
|
||||
printf( "Am29LV640D/Am29LV641D/Am29LV642D" );
|
||||
break;
|
||||
default:
|
||||
printf ( "Unknown (ID 0x%04x)", cid );
|
||||
break;
|
||||
}
|
||||
printf( "\n\tProtected: %04x\n", prot );
|
||||
}
|
||||
|
||||
static int
|
||||
amd_flash_erase_block( parts *ps, uint32_t adr )
|
||||
{
|
||||
int o = 2;
|
||||
|
||||
printf("flash_erase_block 0x%08X\n", adr);
|
||||
|
||||
/* printf("protected: %d\n", amdisprotected(ps, adr)); */
|
||||
|
||||
bus_write( ps, 0x0555 << o, 0x00aa00aa ); /* autoselect p29, sector erase */
|
||||
bus_write( ps, 0x02aa << o, 0x00550055 );
|
||||
bus_write( ps, 0x0555 << o, 0x00800080 );
|
||||
bus_write( ps, 0x0555 << o, 0x00aa00aa );
|
||||
bus_write( ps, 0x02aa << o, 0x00550055 );
|
||||
bus_write( ps, adr, 0x00300030 );
|
||||
|
||||
if (amdstatus(ps, adr, 0xffff)) {
|
||||
printf( "flash_erase_block 0x%08X DONE\n", adr );
|
||||
amd_flash_read_array( ps ); /* AMD reset */
|
||||
return 0;
|
||||
}
|
||||
printf( "flash_erase_block 0x%08X FAILED\n", adr );
|
||||
/* Read Array */
|
||||
amd_flash_read_array( ps ); /* AMD reset */
|
||||
|
||||
return CFI_INTEL_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
static int
|
||||
amd_flash_unlock_block( parts *ps, uint32_t adr )
|
||||
{
|
||||
printf( "flash_unlock_block 0x%08X IGNORE\n", adr );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
amd_flash_program( parts *ps, uint32_t adr, uint32_t data )
|
||||
{
|
||||
int o = 2;
|
||||
int status;
|
||||
|
||||
if (dbg)
|
||||
printf("\nflash_program 0x%08X = 0x%08X\n", adr, data);
|
||||
|
||||
bus_write( ps, 0x0555 << o, 0x00aa00aa ); /* autoselect p29, program */
|
||||
bus_write( ps, 0x02aa << o, 0x00550055 );
|
||||
bus_write( ps, 0x0555 << o, 0x00A000A0 );
|
||||
|
||||
bus_write( ps, adr, data );
|
||||
status = amdstatus( ps, adr, data );
|
||||
/* amd_flash_read_array(ps); */
|
||||
|
||||
return !status;
|
||||
}
|
||||
|
||||
static void
|
||||
amd_flash_read_array( parts *ps)
|
||||
{
|
||||
/* Read Array */
|
||||
bus_write( ps, 0x0, 0x00F000F0 ); /* AMD reset */
|
||||
}
|
||||
|
||||
flash_driver_t amd_32_flash_driver = {
|
||||
4, /* buswidth */
|
||||
"AMD/Fujitsu Standard Command Set",
|
||||
"supported: AMD 29LV640D, 29LV641D, 29LV642D; 2x16 Bit",
|
||||
amd_flash_autodetect,
|
||||
amd_flash_print_info,
|
||||
amd_flash_erase_block,
|
||||
amd_flash_unlock_block,
|
||||
amd_flash_program,
|
||||
amd_flash_read_array,
|
||||
};
|
@ -0,0 +1,307 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2002 ETC s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by Marcel Telka <marcel@telka.sk>, 2002.
|
||||
* Changed by August Hörandl, 2003
|
||||
*
|
||||
* Documentation:
|
||||
* [1] Advanced Micro Devices, "Common Flash Memory Interface Specification Release 2.0",
|
||||
* December 1, 2001
|
||||
* [2] Intel Corporation, "Intel PXA250 and PXA210 Application Processors
|
||||
* Developer's Manual", February 2002, Order Number: 278522-001
|
||||
* [3] Intel Corporation, "Common Flash Interface (CFI) and Command Sets
|
||||
* Application Note 646", April 2000, Order Number: 292204-004
|
||||
* [4] Advanced Micro Devices, "Common Flash Memory Interface Publication 100 Vendor & Device
|
||||
* ID Code Assignments", December 1, 2001, Volume Number: 96.1
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <flash/cfi.h>
|
||||
#include <flash/intel.h>
|
||||
#include <std/mic.h>
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
static int intel_flash_erase_block( parts *ps, uint32_t adr );
|
||||
static int intel_flash_unlock_block( parts *ps, uint32_t adr );
|
||||
static int intel_flash_program( parts *ps, uint32_t adr, uint32_t data );
|
||||
static int intel_flash_erase_block32( parts *ps, uint32_t adr );
|
||||
static int intel_flash_unlock_block32( parts *ps, uint32_t adr );
|
||||
static int intel_flash_program32( parts *ps, uint32_t adr, uint32_t data );
|
||||
|
||||
/* autodetect, we can handle this chip */
|
||||
static int
|
||||
intel_flash_autodetect32( parts *ps, cfi_query_structure_t *cfi )
|
||||
{
|
||||
return (cfi->identification_string.pri_id_code == CFI_VENDOR_INTEL_SCS) && (bus_width( ps ) == 32);
|
||||
}
|
||||
|
||||
static int
|
||||
intel_flash_autodetect( parts *ps, cfi_query_structure_t *cfi )
|
||||
{
|
||||
return (cfi->identification_string.pri_id_code == CFI_VENDOR_INTEL_SCS) && (bus_width( ps ) == 16);
|
||||
}
|
||||
|
||||
static
|
||||
void _intel_flash_print_info( parts *ps, int o )
|
||||
{
|
||||
uint32_t mid, cid;
|
||||
|
||||
mid = (bus_read( ps, 0x00 << o ) & 0xFF);
|
||||
switch (mid) {
|
||||
case STD_MIC_INTEL:
|
||||
printf( "Manufacturer: %s\n", STD_MICN_INTEL );
|
||||
break;
|
||||
default:
|
||||
printf( "Unknown manufacturer (0x%04X)!\n", mid);
|
||||
break;
|
||||
}
|
||||
|
||||
printf( "Chip: " );
|
||||
cid = (bus_read( ps, 0x01 << o ) & 0xFFFF);
|
||||
switch (cid) {
|
||||
case 0x0016:
|
||||
printf( "28F320J3A\n" );
|
||||
break;
|
||||
case 0x0017:
|
||||
printf( "28F640J3A\n" );
|
||||
break;
|
||||
case 0x0018:
|
||||
printf( "28F128J3A\n" );
|
||||
break;
|
||||
case 0x8801:
|
||||
printf( "28F640K3\n" );
|
||||
break;
|
||||
case 0x8802:
|
||||
printf( "28F128K3\n" );
|
||||
break;
|
||||
case 0x8803:
|
||||
printf( "28F256K3\n" );
|
||||
break;
|
||||
case 0x8805:
|
||||
printf( "28F640K18\n" );
|
||||
break;
|
||||
case 0x8806:
|
||||
printf( "28F128K18\n" );
|
||||
break;
|
||||
case 0x8807:
|
||||
printf( "28F256K18\n" );
|
||||
break;
|
||||
default:
|
||||
printf( "Unknown (0x%02X)!\n", cid );
|
||||
break;
|
||||
}
|
||||
|
||||
/* Read Array */
|
||||
bus_write( ps, 0 << o, 0x00FF00FF );
|
||||
}
|
||||
|
||||
static
|
||||
void intel_flash_print_info( parts *ps )
|
||||
{
|
||||
int o = 1;
|
||||
/* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
|
||||
/* TODO */
|
||||
|
||||
/* Clear Status Register */
|
||||
bus_write( ps, 0 << o, 0x0050 );
|
||||
|
||||
/* Read Identifier Command */
|
||||
bus_write( ps, 0 << 0, 0x0090 );
|
||||
|
||||
_intel_flash_print_info( ps, o );
|
||||
}
|
||||
|
||||
static
|
||||
void intel_flash_print_info32( parts *ps )
|
||||
{
|
||||
int o = 2;
|
||||
/* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
|
||||
/* TODO */
|
||||
|
||||
/* Clear Status Register */
|
||||
bus_write( ps, 0 << o, 0x00500050 );
|
||||
|
||||
/* Read Identifier Command */
|
||||
bus_write( ps, 0 << 0, 0x00900090 );
|
||||
|
||||
_intel_flash_print_info( ps, o );
|
||||
}
|
||||
|
||||
static int
|
||||
intel_flash_erase_block( parts *ps, uint32_t adr )
|
||||
{
|
||||
uint16_t sr;
|
||||
|
||||
bus_write( ps, 0, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
|
||||
bus_write( ps, adr, CFI_INTEL_CMD_BLOCK_ERASE );
|
||||
bus_write( ps, adr, CFI_INTEL_CMD_CONFIRM );
|
||||
|
||||
while (!((sr = bus_read( ps, 0 ) & 0xFE) & CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
|
||||
|
||||
switch (sr & ~CFI_INTEL_SR_READY) {
|
||||
case 0:
|
||||
return 0;
|
||||
case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_PROGRAM_ERROR:
|
||||
printf("flash: invalid command seq\n");
|
||||
return CFI_INTEL_ERROR_INVALID_COMMAND_SEQUENCE;
|
||||
case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_VPEN_ERROR:
|
||||
printf("flash: low vpen\n");
|
||||
return CFI_INTEL_ERROR_LOW_VPEN;
|
||||
case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_BLOCK_LOCKED:
|
||||
printf("flash: block locked\n");
|
||||
return CFI_INTEL_ERROR_BLOCK_LOCKED;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return CFI_INTEL_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_flash_unlock_block( parts *ps, uint32_t adr )
|
||||
{
|
||||
uint16_t sr;
|
||||
|
||||
bus_write( ps, 0, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
|
||||
bus_write( ps, adr, CFI_INTEL_CMD_LOCK_SETUP );
|
||||
bus_write( ps, adr, CFI_INTEL_CMD_UNLOCK_BLOCK );
|
||||
|
||||
while (!((sr = bus_read( ps, 0 ) & 0xFE) & CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
|
||||
|
||||
if (sr != CFI_INTEL_SR_READY) {
|
||||
printf("flash: unknown error while unblocking\n");
|
||||
return CFI_INTEL_ERROR_UNKNOWN;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_flash_program( parts *ps, uint32_t adr, uint32_t data )
|
||||
{
|
||||
uint16_t sr;
|
||||
|
||||
bus_write( ps, 0, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
|
||||
bus_write( ps, adr, CFI_INTEL_CMD_PROGRAM1 );
|
||||
bus_write( ps, adr, data );
|
||||
|
||||
while (!((sr = bus_read( ps, 0 ) & 0xFE) & CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
|
||||
|
||||
if (sr != CFI_INTEL_SR_READY) {
|
||||
printf("flash: unknown error while programming\n");
|
||||
return CFI_INTEL_ERROR_UNKNOWN;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_flash_erase_block32( parts *ps, uint32_t adr )
|
||||
{
|
||||
uint32_t sr;
|
||||
|
||||
bus_write( ps, 0, (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) | CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
|
||||
bus_write( ps, adr, (CFI_INTEL_CMD_BLOCK_ERASE << 16) | CFI_INTEL_CMD_BLOCK_ERASE );
|
||||
bus_write( ps, adr, (CFI_INTEL_CMD_CONFIRM << 16) | CFI_INTEL_CMD_CONFIRM );
|
||||
|
||||
while (((sr = bus_read( ps, 0 ) & 0x00FE00FE) & ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
|
||||
|
||||
if (sr != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) {
|
||||
printf( "\nsr = 0x%08X\n", sr );
|
||||
return CFI_INTEL_ERROR_UNKNOWN;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_flash_unlock_block32( parts *ps, uint32_t adr )
|
||||
{
|
||||
uint32_t sr;
|
||||
|
||||
bus_write( ps, 0, (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) | CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
|
||||
bus_write( ps, adr, (CFI_INTEL_CMD_LOCK_SETUP << 16) | CFI_INTEL_CMD_LOCK_SETUP );
|
||||
bus_write( ps, adr, (CFI_INTEL_CMD_UNLOCK_BLOCK << 16) | CFI_INTEL_CMD_UNLOCK_BLOCK );
|
||||
|
||||
while (((sr = bus_read( ps, 0 ) & 0x00FE00FE) & ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
|
||||
|
||||
if (sr != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) {
|
||||
printf( "\nsr = 0x%08X\n", sr );
|
||||
return CFI_INTEL_ERROR_UNKNOWN;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
intel_flash_program32( parts *ps, uint32_t adr, uint32_t data )
|
||||
{
|
||||
uint32_t sr;
|
||||
|
||||
bus_write( ps, 0, (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) | CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
|
||||
bus_write( ps, adr, (CFI_INTEL_CMD_PROGRAM1 << 16) | CFI_INTEL_CMD_PROGRAM1 );
|
||||
bus_write( ps, adr, data );
|
||||
|
||||
while (((sr = bus_read( ps, 0 ) & 0x00FE00FE) & ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
|
||||
|
||||
if (sr != ((CFI_INTEL_SR_READY << 16) | CFI_INTEL_SR_READY)) {
|
||||
printf( "\nsr = 0x%08X\n", sr );
|
||||
return CFI_INTEL_ERROR_UNKNOWN;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_flash_readarray32( parts *ps )
|
||||
{
|
||||
/* Read Array */
|
||||
bus_write( ps, 0, 0x00FF00FF );
|
||||
}
|
||||
|
||||
static void
|
||||
intel_flash_readarray( parts *ps )
|
||||
{
|
||||
/* Read Array */
|
||||
bus_write( ps, 0, 0x00FF00FF );
|
||||
}
|
||||
|
||||
flash_driver_t intel_32_flash_driver = {
|
||||
4, /* buswidth */
|
||||
"Intel Standard Command Set",
|
||||
"supported: 28Fxxxx, 2 x 16 bit",
|
||||
intel_flash_autodetect32,
|
||||
intel_flash_print_info32,
|
||||
intel_flash_erase_block32,
|
||||
intel_flash_unlock_block32,
|
||||
intel_flash_program32,
|
||||
intel_flash_readarray32,
|
||||
};
|
||||
|
||||
flash_driver_t intel_16_flash_driver = {
|
||||
2, /* buswidth */
|
||||
"Intel Standard Command Set",
|
||||
"supported: 28Fxxxx, 1 x 16 bit",
|
||||
intel_flash_autodetect,
|
||||
intel_flash_print_info,
|
||||
intel_flash_erase_block,
|
||||
intel_flash_unlock_block,
|
||||
intel_flash_program,
|
||||
intel_flash_readarray,
|
||||
};
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Flash Memory interface
|
||||
* Copyright (C) 2003 AH
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by August Hörandl <august.hoerandl@gmx.at>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FLASH_H
|
||||
#define FLASH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "part.h"
|
||||
#include "bus.h"
|
||||
#include <flash/cfi.h>
|
||||
|
||||
/* from cfi.c */
|
||||
cfi_query_structure_t *detect_cfi( parts *ps );
|
||||
|
||||
typedef struct {
|
||||
int buswidth; /* supported bus width, 1/2/4 bytes */
|
||||
const char *name;
|
||||
const char *description;
|
||||
int (*flash_autodetect)( parts *ps, cfi_query_structure_t * );
|
||||
void (*flash_print_info)( parts *ps );
|
||||
int (*flash_erase_block)( parts *ps, uint32_t adr );
|
||||
int (*flash_unlock_block)( parts *ps, uint32_t adr );
|
||||
int (*flash_program)( parts *ps, uint32_t adr, uint32_t data );
|
||||
void (*flash_readarray)( parts *ps );
|
||||
} flash_driver_t;
|
||||
|
||||
extern flash_driver_t *flash_driver;
|
||||
extern flash_driver_t *flash_drivers[];
|
||||
|
||||
/* #define flash_print_info flash_driver->flash_print_info */
|
||||
#define flash_erase_block flash_driver->flash_erase_block
|
||||
#define flash_unlock_block flash_driver->flash_unlock_block
|
||||
#define flash_program flash_driver->flash_program
|
||||
#define flash_readarray flash_driver->flash_readarray
|
||||
|
||||
extern void set_flash_driver( parts *ps, cfi_query_structure_t *cfi );
|
||||
|
||||
#define CFI_INTEL_ERROR_UNKNOWN 1
|
||||
#define CFI_INTEL_ERROR_UNSUPPORTED 2
|
||||
#define CFI_INTEL_ERROR_LOW_VPEN 3
|
||||
#define CFI_INTEL_ERROR_BLOCK_LOCKED 4
|
||||
#define CFI_INTEL_ERROR_INVALID_COMMAND_SEQUENCE 5
|
||||
|
||||
#endif /* FLASH_H */
|
Loading…
Reference in New Issue