[ 1873220 ] Merge libbrux into src, and inclow into include. Compiles now.

git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@926 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Kolja Waschk 17 years ago
parent a3547df4c0
commit aae9e008ec

@ -1,6 +1,13 @@
2008-01-18 Kolja Waschk <kawk>
* Warning - the modification 1873220 is not yet completely done!
* Moved the code from libbrux/ subdirectory into appropriate locations in
our src/ subdirectory (Enhancement 1873220):
libbrux/cmd/help.c -> src/cmd/help.c
libbrux/cmd/quit.c -> src/cmd/quit.c
libbrux/cmd/cmd.c + src/cmd.c -> src/cmd/cmd.c
libbrux/cmd/cmd_detectflash.c -> src/cmd/detectflash.c
libbrux/flash + Makefile.am -> src/flash/
* Merged the header files from openwince "include" package, which were
previously moved in inclow/, into our final include/ directory, omitting
@ -9,13 +16,13 @@
common.h -> n/a (use bitmask.h!)
openwince.h (asm/C detection) -> n/a (use #ifdef __ASSEMBLY__)
openwince.h (bitmasks) -> bitmask.h
arm/pxa2x0/mc.h -> bus/pxa2x0.h
brux/bus.h -> bus/driver.h
brux/cmd.h + cmd.h -> cmd.h
brux/cfi.h + brux/flash.h + cmd.h -> flash.h
brux/cfi.h + brux/flash.h+flash.h -> flash.h
brux/bus.h -> bus_driver.h
std/mic.h -> flash/mic.h
device/flash/cfi.h -> flash/cfi.h
device/flash/intel.h -> flash/intel.h
arm/pxa2x0/mc.h -> src/bus/pxa2x0_mc.h
2008-01-17 Kolja Waschk <kawk>

@ -24,7 +24,6 @@
include $(top_srcdir)/Makefile.rules
SUBDIRS = \
libbrux \
doc \
include \
data \
@ -32,7 +31,6 @@ SUBDIRS = \
po
DIST_SUBDIRS = \
inclow \
$(SUBDIRS)
noinst_HEADERS = \

@ -66,6 +66,7 @@ AC_CONFIG_FILES(
src/tap/Makefile
src/part/Makefile
src/bus/Makefile
src/flash/Makefile
src/cmd/Makefile
src/svf/Makefile
src/bsdl/Makefile
@ -133,30 +134,6 @@ else
AM_CONDITIONAL([BISON_LOCATIONS], false)
fi
AC_CONFIG_SUBDIRS(libbrux)
#AC_ARG_WITH(include,
# AC_HELP_STRING([--with-include=PATH], [Absolute path to the openwince includes]),
# openwince_inc="$withval")
#AC_CACHE_CHECK([for the openwince includes], openwince_includes_path, [
# openwince_includes_path="no"
# for openwince_include in $openwince_inc /usr/include/openwince /usr/local/include/openwince; do
# if test -f "$openwince_include/common.h"; then
# openwince_includes_path="$openwince_include"
# break
# fi
# done
#])
#if test "$openwince_includes_path" = "no"; then
# AC_MSG_ERROR([The openwince include package can not be found.])
#fi
#CPPFLAGS="$CPPFLAGS -I$openwince_includes_path -I$openwince_includes_path/device -I$openwince_includes_path/arm"
AC_CONFIG_SUBDIRS(inclow)
CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/inclow"
CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/inclow/device"
CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/inclow/arm"
AC_SEARCH_LIBS([ioperm], [ioperm])
if test "$ac_cv_search_ioperm" != "no"; then
AC_DEFINE(HAVE_IOPERM, 1, [Define to 1 if you have the ioperm() function])

@ -26,12 +26,17 @@ include $(top_srcdir)/Makefile.rules
noinst_HEADERS = \
bsbit.h \
bsdl.h \
bitmask.h \
bus.h \
bus_driver.h \
cable.h \
chain.h \
data_register.h \
cmd.h \
flash.h \
flash/cfi.h \
flash/mic.h \
flash/intel.h \
gettext.h \
instruction.h \
parport.h \

@ -29,7 +29,7 @@
#include <stdint.h>
#include "chain.h"
#include <brux/bus.h>
#include <bus_driver.h>
typedef struct {
int len;

@ -37,14 +37,12 @@
#include <stdio.h>
#include <stdint.h>
#include <bus/driver.h>
#include <bus_driver.h>
/* Following moved here from brux/cfi.h */
#include <flash/cfi.h>
#include <brux/bus.h>
typedef struct {
int width; /* 1 for 8 bits, 2 for 16 bits, 4 for 32 bits, etc. */
cfi_query_structure_t cfi;

@ -41,9 +41,7 @@
#ifndef FLASH_CFI_H
#define FLASH_CFI_H
#include <openwince.h>
#if LANGUAGE == C
#ifndef __ASSEMBLY__
#include <stdint.h>
#endif
@ -62,14 +60,14 @@
#define ALT_VENDOR_ID_OFFSET 0x17
#define ALT_VENDOR_TABLE_ADR_OFFSET 0x19
#if LANGUAGE == C
#ifndef __ASSEMBLY__
typedef struct cfi_query_identification_string {
uint16_t pri_id_code;
void *pri_vendor_tbl;
uint16_t alt_id_code;
void *alt_vendor_tbl;
} cfi_query_identification_string_t;
#endif /* LANGUAGE == C */
#endif /* __ASSEMBLY__ */
/* Algorithm command set & control interface ID codes - see Table 1 in [2] */
@ -97,7 +95,7 @@ typedef struct cfi_query_identification_string {
#define MAX_BLOCK_ERASE_TIMEOUT_OFFSET 0x25 /* Maximum timeout per individual block erase */
#define MAX_CHIP_ERASE_TIMEOUT_OFFSET 0x26 /* Maximum timeout for chip erase */
#if LANGUAGE == C
#ifndef __ASSEMBLY__
typedef struct cfi_query_system_interface_information {
uint16_t vcc_min_wev; /* in mV */
uint16_t vcc_max_wev; /* in mV */
@ -112,7 +110,7 @@ typedef struct cfi_query_system_interface_information {
uint32_t max_block_erase_timeout; /* in ms, 0 - not supported */
uint32_t max_chip_erase_timeout; /* in ms, 0 - not supported */
} cfi_query_system_interface_information_t;
#endif /* LANGUAGE == C */
#endif /* __ASSEMBLY__ */
/* Device geometry definition - see 4.3.4 in [1] */
@ -122,7 +120,7 @@ typedef struct cfi_query_system_interface_information {
#define NUMBER_OF_ERASE_REGIONS_OFFSET 0x2C /* Number of Erase Block Regions */
#define ERASE_BLOCK_REGION_OFFSET 0x2D /* Erase Block Region Information */
#if LANGUAGE == C
#ifndef __ASSEMBLY__
typedef struct cfi_erase_block_region cfi_erase_block_region_t;
typedef struct cfi_device_geometry {
@ -137,7 +135,7 @@ struct cfi_erase_block_region {
uint32_t erase_block_size; /* in B */
uint32_t number_of_erase_blocks;
};
#endif /* LANGUAGE == C */
#endif /* __ASSEMBLY__ */
/* Device interface code assignments (for cfi_device_geometry.device_interface) - see Table 2 in [2] */
@ -149,12 +147,12 @@ struct cfi_erase_block_region {
/* CFI Query structure - see 4.3.1 in [1] */
#if LANGUAGE == C
#ifndef __ASSEMBLY__
typedef struct cfi_query_structure {
cfi_query_identification_string_t identification_string;
cfi_query_system_interface_information_t system_interface_info;
cfi_device_geometry_t device_geometry;
} cfi_query_structure_t;
#endif /* LANGUAGE == C */
#endif /* __ASSEMBLY__ */
#endif /* FLASH_CFI_H */

@ -40,7 +40,7 @@
#ifndef FLASH_INTEL_H
#define FLASH_INTEL_H
#include <openwince.h>
#include <bitmask.h>
/* Intel CFI commands - see Table 4. in [1] and Table 3. in [2] */

@ -28,7 +28,7 @@
#include <stdio.h>
#include <stdint.h>
#include <brux/flash.h>
#include <flash.h>
#include "chain.h"
#include "bus.h"

@ -25,7 +25,7 @@
#ifndef STATE_H
#define STATE_H
#include <common.h>
#include <bitmask.h>
#include "chain.h"

@ -24,6 +24,7 @@
include $(top_srcdir)/Makefile.rules
SUBDIRS = \
flash \
lib \
tap \
part \
@ -54,7 +55,7 @@ bsdl2jtag_SOURCES = \
bsdl2jtag.c
jtag_DEPENDENCIES = \
../libbrux/libbrux.a \
flash/libflash.a \
lib/libjtaglib.a \
tap/libtap.a \
part/libpart.a \
@ -73,9 +74,8 @@ jtag_LDADD = \
-Ltap -ltap \
-Lpart -lpart \
-Llib -ljtaglib \
-L../libbrux -lbrux \
-Lflash -lflash \
-Lcmd -lcmd \
-L../libbrux -lbrux \
-Lbus -lbus \
-lm \
@FTD2XXLIB@ \

@ -34,7 +34,7 @@
#include "sysdep.h"
#include <jtag.h>
#include <brux/cmd.h>
#include <cmd.h>
#include "bsdl.h"

@ -30,7 +30,7 @@
#include <string.h>
#include <jtag.h>
#include <brux/cmd.h>
#include <cmd.h>
#include "bsdl_bison.h"

@ -41,6 +41,7 @@ libbus_a_SOURCES = \
ppc405ep.c \
prototype.c \
pxa2x0.c \
pxa2x0_mc.h \
sa1110.c \
s3c4510x.c \
sh7727.c \

@ -36,14 +36,15 @@
#include <stdint.h>
#include <string.h>
#include <pxa2x0/mc.h>
#include "part.h"
#include "bus.h"
#include "bssignal.h"
#include "jtag.h"
#include "buses.h"
#include "pxa2x0_mc.h"
/*
* the following defines are used in proc field of the the
* bus_params_t structure and are used in various functions

@ -45,9 +45,9 @@
#ifndef PXA2X0_MC_H
#define PXA2X0_MC_H
#include <openwince.h>
#include <bitmask.h>
#if LANGUAGE == C
#ifndef __ASSEMBLY__
#include <stdint.h>
#endif
@ -63,7 +63,7 @@
#define MC_BASE 0x48000000
#if LANGUAGE == C
#ifndef __ASSEMBLY__
typedef volatile struct MC_registers {
uint32_t mdcnfg;
uint32_t mdrefr;
@ -119,7 +119,7 @@ typedef volatile struct MC_registers {
#if !defined(PXA2X0_NOPXA260)
#define SA1111CR MC_pointer->sa1111cr
#endif /* PXA260 and above only */
#endif /* LANGUAGE == C */
#endif /* __ASSEMBLY__ */
#define MDCNFG_OFFSET 0x00
#define MDREFR_OFFSET 0x04

@ -31,6 +31,9 @@ libcmd_a_SOURCES = \
reset.c \
discovery.c \
detect.c \
detectflash.c \
help.c \
quit.c \
signal.c \
salias.c \
bit.c \

@ -123,3 +123,61 @@ cmd_test_cable( void )
printf( _("Error: Cable not configured. Please use '%s' command first!\n"), "cable" );
return 0;
}
/* Remainder copied from libbrux/cmd/cmd.c */
int
cmd_run( char *params[] )
{
int i;
if (!params[0])
return 1;
for (i = 0; cmds[i]; i++)
if (strcasecmp( cmds[i]->name, params[0] ) == 0) {
int r = cmds[i]->run( params );
if (r < 0)
printf( _("%s: syntax error!\n"), params[0] );
return r;
}
printf( _("%s: unknown command\n"), params[0] );
return 1;
}
int
cmd_params( char *params[] )
{
int i = 0;
while (params[i])
i++;
return i;
}
int
cmd_get_number( char *s, unsigned int *i )
{
int n;
int r;
size_t l;
if (!s || !i)
return -1;
l = strlen( s );
n = -1;
r = sscanf( s, "0x%x%n", i, &n);
if (r == 1 && n == l)
return 0;
n = -1;
r = sscanf( s, "%u%n", i, &n );
if (r == 1 && n == l)
return 0;
return -1;
}

@ -0,0 +1,69 @@
/*
* $Id$
*
* Copyright (C) 2003 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>, 2003.
*
*/
#include "sysdep.h"
#include <stdio.h>
#include <flash.h>
#include <cmd.h>
static int
cmd_detectflash_run( char *params[] )
{
uint32_t adr;
if (cmd_params( params ) != 2)
return -1;
if (!bus) {
printf( _("Error: Bus driver missing.\n") );
return 1;
}
if (cmd_get_number( params[1], &adr ))
return -1;
detectflash( bus, adr );
return 1;
}
static void
cmd_detectflash_help( void )
{
printf( _(
"Usage: %s ADDRESS\n"
"Detect flash memory type connected to a part.\n"
"\n"
"ADDRESS Base address for memory region\n"
), "detectflash" );
}
cmd_t cmd_detectflash = {
"detectflash",
N_("detect parameters of flash chips attached to a part"),
cmd_detectflash_help,
cmd_detectflash_run
};

@ -0,0 +1,76 @@
/*
* $Id$
*
* Copyright (C) 2003 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>, 2003.
*
*/
#include "sysdep.h"
#include <stdio.h>
#include <string.h>
#include <cmd.h>
static int
cmd_help_run( char *params[] )
{
int i;
/* short description generation */
if (!params[1]) {
printf( _("Command list:\n\n") );
for (i = 0; cmds[i]; i++)
printf( _("%-13s %s\n"), cmds[i]->name, cmds[i]->desc ? _(cmds[i]->desc) : _("(no description available)") );
printf( _("\nType \"help COMMAND\" for details about a particular command.\n") );
return 1;
}
if (params[2])
return -1;
/* search and print help for a particular command */
for (i = 0; cmds[i]; i++)
if (strcasecmp( cmds[i]->name, params[1] ) == 0) {
if (cmds[i]->help)
cmds[i]->help();
return 1;
}
printf( _("%s: unknown command\n"), params[1] );
return 1;
}
static void
cmd_help_help( void )
{
printf( _(
"Usage: %s [COMMAND]\n"
"Print short help for COMMAND, or list of available commands.\n"
), "help" );
}
cmd_t cmd_help = {
"help",
N_("display this help"),
cmd_help_help,
cmd_help_run
};

@ -0,0 +1,54 @@
/*
* $Id$
*
* Copyright (C) 2003 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>, 2003.
*
*/
#include "sysdep.h"
#include <stdio.h>
#include <cmd.h>
static int
cmd_quit_run( char *params[] )
{
if (params[1])
return -1;
return 0;
}
static void
cmd_quit_help( void )
{
printf( _(
"Usage: %s\n"
"Exit from %s.\n"
), "quit", PACKAGE );
}
cmd_t cmd_quit = {
"quit",
N_("exit and terminate this session"),
cmd_quit_help,
cmd_quit_run
};

@ -29,7 +29,7 @@
#include <ctype.h>
#include <string.h>
#include <brux/cmd.h>
#include <cmd.h>
#include <bsdl.h>

@ -41,7 +41,6 @@
#include <flash/cfi.h>
#include <flash/intel.h>
#include <brux/cfi.h>
#include "bus.h"
#include "flash.h"

@ -0,0 +1,34 @@
#
# $Id: Makefile.am 506 2003-08-13 10:05:15Z telka $
#
# 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.
#
include $(top_srcdir)/Makefile.rules
noinst_LIBRARIES = libflash.a
libflash_a_SOURCES = \
amd.c \
amd_flash.c \
cfi.c \
detectflash.c \
intel.c \
jedec.c

@ -0,0 +1,391 @@
/*
* $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>
* Modified by Marcel Telka <marcel@telka.sk>, 2003.
*
* 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 "sysdep.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <unistd.h>
#include <flash.h>
#include <bus.h>
static int dbg = 0;
static int amd_flash_erase_block( cfi_array_t *cfi_array, uint32_t adr );
static int amd_flash_unlock_block( cfi_array_t *cfi_array, uint32_t adr );
static int amd_flash_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data );
static void amd_flash_read_array( cfi_array_t *cfi_array );
/* The code below assumes a connection of the flash chip address LSB (A0)
* to A0, A1 or A2 of the CPU bus dependent on the bus width, which is the
* most common connection pattern:
* 8 Bit devices: A0..Ax connected to A0..Ax of CPU bus
* 16 Bit devices: A0..Ax connected to A1..Ax+1 of CPU bus
* 32 Bit devices: A0..Ax connected to A2..Ax+2 of CPU bus
* The offset "o" is used here dependent on the bus width (8, 16 or 32 bit) to
* align the patterns emitted on the address lines at either A0, A1 or A2. */
static int o;
/* NOTE: It does not work for SoC chips or boards with extra address decoders
* that do address alignment themselves, such as the Samsung S3C4510B. The bus
* driver has to deal with this. - kawk 2008-01 */
/* autodetect, we can handle this chip */
static int
amd_flash_autodetect32( cfi_array_t *cfi_array )
{
if(cfi_array->bus_width != 4) return 0;
o = 2; /* Heuristic */
return (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_AMD_SCS);
}
static int
amd_flash_autodetect16( cfi_array_t *cfi_array )
{
if(cfi_array->bus_width != 2) return 0;
o = 1; /* Heuristic */
return (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_AMD_SCS);
}
static int
amd_flash_autodetect8( cfi_array_t *cfi_array )
{
if(cfi_array->bus_width != 1) return 0;
o = 0; /* Heuristic */
return (cfi_array->cfi_chips[0]->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
*/
#if 0
static int
amdstatus29( parts *ps, uint32_t adr, uint32_t data )
{
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;
}
#endif /* 0 */
#if 1
/*
* second implementation: see [1], page 30
*/
static int
amdstatus( bus_t *bus, 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( bus, adr );
uint32_t data2 = bus_read( bus, adr );
/*printf("amdstatus %d: %04X/%04X %04X/%04X \n", */
/* timeout, data1, data2, (data1 & togglemask), (data2 & togglemask)); */
if ( (data1 & togglemask) == (data2 & togglemask))
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;
}
#else /* 1 */
/* Note: This implementation of amdstatus() has been added by patch
[ 1429825 ] EJTAG driver (some remaining patch lines for flash/amd.c)
It's a quirk workaround and seems to break status polling for other chips.
Therefore it's deactivated at the moment but kept for reference. */
/*
* second implementation: see [1], page 30
*/
static int
amdstatus( bus_t *bus, 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 */
uint32_t data1, data2;
data1 = bus_read( bus, adr );
for (timeout = 0; timeout < 100; timeout++) {
data2 = bus_read( bus, adr );
/*printf("amdstatus %d: %04X/%04X %04X/%04X \n", */
/* timeout, data1, data2, (data1 & togglemask), (data2 & togglemask)); */
/* Work around an issue with RTL8181: toggle bits don't
toggle when reading the same flash address repeatedly
without any other memory access in between. Other
bits reflect the current status, and data after the
operation is complete - only Q6/Q2 bits don't toggle
when they should. Looks like the CPU not deasserting
CE or OE, so data is output to the bus continuously.
So, check for the correct data read twice instead. */
/*if ( (data1 & togglemask) == (data2 & togglemask)) */
if ( (data1 == data) && (data2 == data) )
return 1;
/* if ( (data1 & dq5mask) != 0 ) TODO */
/* return 0; */
if (dbg)
printf( "amdstatus %d: %04X/%04X\n", timeout, data1, data2 );
else
printf( "." );
usleep( 100 );
data1 = data2;
}
return 0;
}
#endif /* 0 */
#if 0
static int
amdisprotected( parts *ps, cfi_array_t *cfi_array, uint32_t adr )
{
uint32_t data;
bus_write( ps, cfi_array->address + (0x0555 << o), 0x00aa00aa ); /* autoselect p29, sector erase */
bus_write( ps, cfi_array->address + (0x02aa << o), 0x00550055 );
bus_write( ps, cfi_array->address + (0x0555 << o), 0x00900090 );
data = bus_read( ps, adr + (0x0002 << 2) );
/* Read Array */
amd_flash_read_array( ps ); /* AMD reset */
return ((data & 0x00ff00ff) != 0);
}
#endif /* 0 */
static void
amd_flash_print_info( cfi_array_t *cfi_array )
{
int mid, cid, prot;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00aa00aa ); /* autoselect p29 */
bus_write( bus, cfi_array->address + (0x02aa << o), 0x00550055 );
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00900090 );
mid = bus_read( bus, cfi_array->address + (0x00 << o) ) & 0xFFFF;
cid = bus_read( bus, cfi_array->address + (0x01 << o) ) & 0xFFFF;
prot = bus_read( bus, cfi_array->address + (0x02 << o) ) & 0xFF;
amd_flash_read_array( cfi_array ); /* AMD reset */
printf( _("Chip: AMD Flash\n\tManufacturer: ") );
switch (mid) {
case 0x0001:
printf( _("AMD") );
break;
case 0x0020:
printf( _("ST/Samsung") );
break;
case 0x002C:
printf( _("Macronix") );
break;
default:
printf( _("Unknown manufacturer (ID 0x%04x)"), mid );
break;
}
printf( _("\n\tChip: ") );
switch (cid) {
case 0x004F:
printf( _("Am29LV040B") );
break;
case 0x22D7:
printf( _("Am29LV640D/Am29LV641D/Am29LV642D") );
break;
case 0x225B:
printf( _("Am29LV800B") );
break;
case 0x2249:
printf( _("MX29LV160B") );
break;
case 0x0049:
printf( _("AM29LV160DB") );
break;
case 0x0093:
printf( _("Am29LV065D") );
break;
case 0x00ca:
printf( _("M29W320DT") );
break;
case 0x00cb:
printf( _("M29W320DB") );
break;
default:
printf ( _("Unknown (ID 0x%04x)"), cid );
break;
}
printf( _("\n\tProtected: %04x\n"), prot );
/* Read Array */
bus_write( bus, cfi_array->address + (0x0000 << o), 0x00ff00ff );
}
static int
amd_flash_erase_block( cfi_array_t *cfi_array, uint32_t adr )
{
bus_t *bus = cfi_array->bus;
printf("flash_erase_block 0x%08X\n", adr);
/* printf("protected: %d\n", amdisprotected(ps, cfi_array, adr)); */
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00aa00aa ); /* autoselect p29, sector erase */
bus_write( bus, cfi_array->address + (0x02aa << o), 0x00550055 );
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00800080 );
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00aa00aa );
bus_write( bus, cfi_array->address + (0x02aa << o), 0x00550055 );
bus_write( bus, adr, 0x00300030 );
if (amdstatus( bus, adr, 0xffff )) {
printf( "flash_erase_block 0x%08X DONE\n", adr );
amd_flash_read_array( cfi_array ); /* AMD reset */
return 0;
}
printf( "flash_erase_block 0x%08X FAILED\n", adr );
/* Read Array */
amd_flash_read_array( cfi_array ); /* AMD reset */
return FLASH_ERROR_UNKNOWN;
}
static int
amd_flash_unlock_block( cfi_array_t *cfi_array, uint32_t adr )
{
printf( "flash_unlock_block 0x%08X IGNORE\n", adr );
return 0;
}
static int
amd_flash_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data )
{
int status;
bus_t *bus = cfi_array->bus;
if (dbg)
printf("\nflash_program 0x%08X = 0x%08X\n", adr, data);
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00aa00aa ); /* autoselect p29, program */
bus_write( bus, cfi_array->address + (0x02aa << o), 0x00550055 );
bus_write( bus, cfi_array->address + (0x0555 << o), 0x00A000A0 );
bus_write( bus, adr, data );
status = amdstatus( bus, adr, data );
/* amd_flash_read_array(ps); */
return !status;
}
static void
amd_flash_read_array( cfi_array_t *cfi_array )
{
/* Read Array */
bus_write( cfi_array->bus, cfi_array->address, 0x00F000F0 ); /* AMD reset */
}
flash_driver_t amd_32_flash_driver = {
4, /* buswidth */
N_("AMD/Fujitsu Standard Command Set"),
N_("supported: AMD 29LV640D, 29LV641D, 29LV642D; 2x16 Bit"),
amd_flash_autodetect32,
amd_flash_print_info,
amd_flash_erase_block,
amd_flash_unlock_block,
amd_flash_program,
amd_flash_read_array,
};
flash_driver_t amd_16_flash_driver = {
2, /* buswidth */
N_("AMD/Fujitsu Standard Command Set"),
N_("supported: AMD 29LV800B; 1x16 Bit"),
amd_flash_autodetect16,
amd_flash_print_info,
amd_flash_erase_block,
amd_flash_unlock_block,
amd_flash_program,
amd_flash_read_array,
};
flash_driver_t amd_8_flash_driver = {
1, /* buswidth */
N_("AMD/Fujitsu Standard Command Set"),
N_("supported: AMD 29LV160, AMD 29LV065D, AMD 29LV040B; 1x8 Bit"),
amd_flash_autodetect8,
amd_flash_print_info,
amd_flash_erase_block,
amd_flash_unlock_block,
amd_flash_program,
amd_flash_read_array,
};

@ -0,0 +1,353 @@
/*
* $Id: amd_flash.c,v 1.0 20/09/2006 12:38:01 $
*
* AMD 8 bit flash driver for AM29F040B & AM29LV040B
* Copyright (C) 2006 Kila Medical Systems.
*
* 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 Ajith Kumar P.C <ajithpc@kila.com>
*
* Documentation:
* [1] Spansion, Am29F040B Data Sheet
* [2] Spansion, Am29LV040B Data Sheet
*/
#include "sysdep.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <unistd.h>
#include <flash.h>
#include <bus.h>
//write specific
#define AMD_SECTOR_PROTECTED
//Read Specific
#define AMD_READ_IN_ERASE_SUSPENDED_SECTOR
#define AMD_READ_IN_NON_ERASE_SUSPENDED_SECTOR
#define AMD_NORMAL_READ
#define AMD_UNKNOWN_READ
//Mode
#define AMD_ERASE_SUSPEND_MODE
#define AMD_READING_MODE
#define AMD_EMBEDDED_ERASE_ALGORITHM
#define AMD_EMBEDDED_PROGRAM_ALGORITHM
#define AMD_UNDEFINED_MODE
#define FLASH_ERASE_ERROR -5
#define ERASE_FLASH_SUCCESS 1
#define AMD_29xx040B 1
#define AMD_BYPASS_UNLOCK_ALGORITHM 1
#define AMD_STANDARD_WRITE_ALGORITHM 0
#define AMD_BYPASS_UNLOCK_MODE 1
#define AMD_STANDARD_MODE 0
struct
{
unsigned long flash;
unsigned short algorithm;
unsigned short unlock_bypass;
}
var_forced_detection;
int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array );
static int amd_29xx040_autodetect( cfi_array_t *cfi_array );
static int amd_29xx040_status( bus_t *bus, uint32_t adr, unsigned short data );
static void amd_29xx040_print_info( cfi_array_t *cfi_array );
static void amd_29xx040_read_array( cfi_array_t *cfi_array );
static int amd_29xx040_erase_block( cfi_array_t *cfi_array, uint32_t adr );
static int amd_29xx040_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data );
static int amd_29xx040_unlock_block( cfi_array_t *cfi_array, uint32_t adr );
int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
{
int mid;
int did;
bus_area_t area;
cfi_query_structure_t *cfi ;
if (!cfi_array || !bus)
return -1; /* invalid parameters */
*cfi_array = calloc( 1, sizeof (cfi_array_t) );
if (!*cfi_array)
return -2; /* out of memory */
bus_write( bus, adr+0x0, 0xf0 );
bus_write( bus, adr+0x555, 0xaa );
bus_write( bus, adr+0x2AA, 0x55 );
bus_write( bus, adr+0x555, 0x90 );
mid = bus_read( bus, adr+0x0);
did = bus_read( bus, adr+0x1);
bus_write( bus, adr+0x0, 0xf0 );
printf( "%s: mid %x, did %x\n", __FUNCTION__, mid, did );
if (mid != 0x01)
return -1;
switch(did)
{
case 0xA4:
var_forced_detection.flash = AMD_29xx040B;
break;
case 0x4F:
var_forced_detection.flash = AMD_29xx040B;
var_forced_detection.algorithm = AMD_BYPASS_UNLOCK_ALGORITHM;
break;
default:
break;
}
(*cfi_array)->bus = bus;
(*cfi_array)->address = 0;
if (bus_area( bus, adr+0, &area ) != 0)
return -8; /* bus width detection failed */
unsigned int bw = area.width;
int ba,i;
if (bw != 8 && bw != 16 && bw != 32)
return -3; /* invalid bus width */
(*cfi_array)->bus_width = ba = bw / 8;
(*cfi_array)->cfi_chips = calloc( ba, sizeof (cfi_chip_t *) );
if (!(*cfi_array)->cfi_chips)
return -2;
for ( i=0; i<ba; i++ )
{
(*cfi_array)->cfi_chips[i] = calloc( 1, sizeof (cfi_chip_t) );
if (!(*cfi_array)->cfi_chips[i])
return -2; /* out of memory */
(*cfi_array)->cfi_chips[i]->width = 1; //ba;
cfi = &(*cfi_array)->cfi_chips[i]->cfi;
cfi->identification_string.pri_id_code = CFI_VENDOR_NULL;
cfi->identification_string.pri_vendor_tbl = NULL;
cfi->identification_string.alt_id_code = 0;
cfi->identification_string.alt_vendor_tbl = NULL;
cfi->device_geometry.device_size = 512*1024;
cfi->device_geometry.device_interface = 0; // x 8
cfi->device_geometry.max_bytes_write = 32; //not used
cfi->device_geometry.number_of_erase_regions = 1;
cfi->device_geometry.erase_block_regions =
malloc( cfi->device_geometry.number_of_erase_regions * sizeof (cfi_erase_block_region_t) );
if (!cfi->device_geometry.erase_block_regions)
return -2; /* out of memory */
cfi->device_geometry.erase_block_regions[i].erase_block_size = 64 * 1024;
cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks = 8;
//Add other details for info
}
return 0;
}
static int amd_29xx040_autodetect( cfi_array_t *cfi_array )
{
return(var_forced_detection.flash == AMD_29xx040B); //Non-CFI Am29xx040B flash
}
static int amd_29xx040_status( bus_t *bus, uint32_t adr, unsigned short data )
{
short timeout;
unsigned short dq7bit,dq7mask,dq5mask;
unsigned short data1;
dq7mask = (1 << 7);
dq5mask = (1 << 5);
dq7bit = data & dq7mask;
for (timeout = 0; timeout < 1000; timeout++) //typical sector erase time = 0.7 sec
{
data1 = (unsigned short)(bus_read( bus, adr ) & 0xFF);
if((data1 & dq7mask) == dq7bit)
return 1; //Success
if((data1 & dq5mask) == dq5mask)
{
data1 = (unsigned short)(bus_read( bus, adr ) & 0xFF);
if((data1 & dq7mask) == dq7bit)
{
return 1; //Success
}
else
{
return 0; //Failure - Needs a reset command to return back to read array data
}
}
usleep (50);
}
return 0; //hardware failure
}
static void amd_29xx040_print_info( cfi_array_t *cfi_array )
{
int mid, did, prot;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address + 0x0, 0xf0 );
bus_write( bus, cfi_array->address + 0x555, 0xaa );
bus_write( bus, cfi_array->address + 0x2AA, 0x55 );
bus_write( bus, cfi_array->address + 0x555, 0x90 );
mid = bus_read( bus, cfi_array->address + 0x0);
did = bus_read( bus, cfi_array->address + 0x1);
prot = bus_read( bus, cfi_array->address + 0x2);
bus_write( bus, cfi_array->address + 0x0, 0xf0 );
printf( "%s: mid %x, did %x\n", __FUNCTION__, mid, did );
// amd_29xx040_read_array( cfi_array ); /* AMD reset */
switch (mid)
{
case 0x01:
printf( _("Chip: AMD Flash\n\tPartNumber: ") );
break;
default:
printf( _("Unknown manufacturer (ID 0x%04x)"), mid );
break;
}
printf( _("\n\tChip: ") );
switch (did) {
case 0xA4:
printf( _("Am29C040B\t-\t") );
printf( _("5V Flash\n") );
break;
case 0x4F:
printf( _("Am29LV040B\t-\t") );
printf( _("3V Flash\n") );
break;
default:
printf ( _("Unknown (ID 0x%04x)"), did );
break;
}
printf( _("\n\tProtected: %04x\n"), prot );
}
static void amd_29xx040_read_array( cfi_array_t *cfi_array )
{
/* Read Array */
if(var_forced_detection.unlock_bypass == AMD_BYPASS_UNLOCK_MODE)
{
bus_write( bus, cfi_array->address + 0x555, 0x90 );
bus_write( bus, cfi_array->address + 0x2AA, 0x00 );
usleep(100);
var_forced_detection.unlock_bypass = AMD_STANDARD_MODE;
}
bus_write( cfi_array->bus, cfi_array->address + 0x0, 0x0F0 ); /* AMD reset */
}
static int amd_29xx040_erase_block( cfi_array_t *cfi_array, uint32_t adr )
{
bus_t *bus = cfi_array->bus;
printf("flash_erase_block 0x%08X\n", adr);
/* printf("protected: %d\n", amdisprotected(ps, adr)); */
if(var_forced_detection.unlock_bypass == AMD_BYPASS_UNLOCK_MODE)
{
bus_write( bus, cfi_array->address + 0x555, 0x90 );
bus_write( bus, cfi_array->address + 0x2AA, 0x00 );
usleep(100);
var_forced_detection.unlock_bypass = AMD_STANDARD_MODE;
}
bus_write( bus, cfi_array->address + 0x0, 0xf0 );
bus_write( bus, cfi_array->address + 0x555, 0xaa );
bus_write( bus, cfi_array->address + 0x2AA, 0x55 );
bus_write( bus, cfi_array->address + 0x555, 0x80 );
bus_write( bus, cfi_array->address + 0x555, 0xaa );
bus_write( bus, cfi_array->address + 0x2AA, 0x55 );
// bus_write( bus, cfi_array->address + 0x555, 0x10 ); //Chip Erase
bus_write( bus, adr, 0x30 ); //Sector erase
if (amd_29xx040_status( bus, adr, 0xff )) {
printf( "flash_erase_block 0x%08X DONE\n", adr );
amd_29xx040_read_array( cfi_array ); /* AMD reset */
return ERASE_FLASH_SUCCESS;
}
printf( "flash_erase_block 0x%08X FAILED\n", adr );
/* Read Array */
amd_29xx040_read_array( cfi_array ); /* AMD reset */
return FLASH_ERASE_ERROR;
}
static int amd_29xx040_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data )
{
int status;
bus_t *bus = cfi_array->bus;
if (0)
printf("\nflash_program 0x%08X = 0x%08X\n", adr, data);
if(var_forced_detection.algorithm == AMD_BYPASS_UNLOCK_ALGORITHM)
{
if(var_forced_detection.unlock_bypass != AMD_BYPASS_UNLOCK_MODE)
{
bus_write( bus, cfi_array->address + 0x555, 0xaa );
bus_write( bus, cfi_array->address + 0x2AA, 0x55 );
bus_write( bus, cfi_array->address + 0x555, 0x20 );
usleep(1000);
var_forced_detection.unlock_bypass = AMD_BYPASS_UNLOCK_MODE;
}
}
else
{
bus_write( bus, cfi_array->address + 0x555, 0xaa );
bus_write( bus, cfi_array->address + 0x2AA, 0x55 );
}
bus_write( bus, cfi_array->address + 0x555, 0xA0 );
bus_write( bus, adr, data );
status = amd_29xx040_status( bus, adr, data );
/* amd_29xx040_read_array(cfi_array); */
return !status;
}
static int amd_29xx040_unlock_block( cfi_array_t *cfi_array, uint32_t adr )
{
printf( "flash_unlock_block 0x%08X IGNORE\n", adr );
return 0;
}
flash_driver_t amd_29xx040_flash_driver = {
1, /* buswidth */
N_("AMD Standard Command Set"),
N_("supported: AMD 29LV040B, 29C040B, 1x8 Bit"),
amd_29xx040_autodetect,
amd_29xx040_print_info,
amd_29xx040_erase_block,
amd_29xx040_unlock_block,
amd_29xx040_program,
amd_29xx040_read_array,
};

@ -0,0 +1,258 @@
/*
* $Id$
*
* Copyright (C) 2002, 2003 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, 2003.
*
* Documentation:
* [1] JEDEC Solid State Technology Association, "Common Flash Interface (CFI)",
* September 1999, Order Number: JESD68
* [2] Intel Corporation, "Common Flash Interface (CFI) and Command Sets
* Application Note 646", April 2000, Order Number: 292204-004
*
*/
#include "sysdep.h"
#include <stdint.h>
#include <stdlib.h>
#include <flash/cfi.h>
#include <flash.h>
#include <bus.h>
void
cfi_array_free( cfi_array_t *cfi_array )
{
if (!cfi_array)
return;
if (cfi_array->cfi_chips) {
int i;
for (i = 0; i < cfi_array->bus_width; i++) {
if (!cfi_array->cfi_chips[i])
continue;
free( cfi_array->cfi_chips[i]->cfi.device_geometry.erase_block_regions );
free( cfi_array->cfi_chips[i] );
}
free( cfi_array->cfi_chips );
}
free( cfi_array );
}
int
cfi_detect( bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
{
unsigned int bw; /* bus width */
unsigned int d; /* data offset */
int ba; /* bus width address multiplier */
int ma; /* flash mode address multiplier */
bus_area_t area;
if (!cfi_array || !bus)
return -1; /* invalid parameters */
*cfi_array = calloc( 1, sizeof (cfi_array_t) );
if (!*cfi_array)
return -2; /* out of memory */
(*cfi_array)->bus = bus;
(*cfi_array)->address = adr;
if (bus_area( bus, adr, &area ) != 0)
return -8; /* bus width detection failed */
bw = area.width;
if (bw != 8 && bw != 16 && bw != 32)
return -3; /* invalid bus width */
(*cfi_array)->bus_width = ba = bw / 8;
(*cfi_array)->cfi_chips = calloc( ba, sizeof (cfi_chip_t *) );
if (!(*cfi_array)->cfi_chips)
return -2; /* out of memory */
for (d = 0; d < bw; d += 8) {
#define A(off) (adr + (off) * ba * ma)
#define D(data) ((data) << d)
#define gD(data) (((data) >> d) & 0xFF)
#define read1(off) gD(bus_read( bus, A(off) ))
#define read2(off) (bus_read_start( bus, A(off) ), gD(bus_read_next( bus, A((off) + 1) )) | gD(bus_read_end( bus )) << 8)
#define write1(off,data) bus_write( bus, A(off), D(data) )
cfi_query_structure_t *cfi;
uint32_t tmp;
int ret = -4; /* CFI not detected (Q) */
/* detect CFI capable devices - see Table 1 in [1] */
for (ma = 1; ma <= 4; ma *= 2) {
write1( CFI_CMD_QUERY_OFFSET, CFI_CMD_QUERY );
if (read1(CFI_QUERY_ID_OFFSET) == 'Q') {
ret = -5; /* CFI not detected (R) */
if (read1(CFI_QUERY_ID_OFFSET + 1) == 'R')
break;
}
write1( 0, CFI_CMD_READ_ARRAY1 );
}
if (ma > 4)
return ret; /* CFI not detected (Q or R) */
if (read1(CFI_QUERY_ID_OFFSET + 2) != 'Y') {
write1( 0, CFI_CMD_READ_ARRAY1 );
return -6; /* CFI not detected (Y) */
}
(*cfi_array)->cfi_chips[d / 8] = calloc( 1, sizeof (cfi_chip_t) );
if (!(*cfi_array)->cfi_chips[d / 8]) {
write1( 0, CFI_CMD_READ_ARRAY1 );
return -2; /* out of memory */
}
cfi = &(*cfi_array)->cfi_chips[d / 8]->cfi;
/* Identification string - see Table 6 in [1] */
cfi->identification_string.pri_id_code = read2(PRI_VENDOR_ID_OFFSET);
cfi->identification_string.pri_vendor_tbl = NULL;
cfi->identification_string.alt_id_code = read2(ALT_VENDOR_ID_OFFSET);
cfi->identification_string.alt_vendor_tbl = NULL;
/* System interface information - see Table 7 in [1] */
tmp = read1(VCC_MIN_WEV_OFFSET);
cfi->system_interface_info.vcc_min_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
tmp = read1(VCC_MAX_WEV_OFFSET);
cfi->system_interface_info.vcc_max_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
tmp = read1(VPP_MIN_WEV_OFFSET);
cfi->system_interface_info.vpp_min_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
tmp = read1(VPP_MAX_WEV_OFFSET);
cfi->system_interface_info.vpp_max_wev = ((tmp >> 4) & 0xF) * 1000 + (tmp & 0xF) * 100;
/* TODO: Add out of range checks for timeouts */
tmp = read1(TYP_SINGLE_WRITE_TIMEOUT_OFFSET);
cfi->system_interface_info.typ_single_write_timeout = tmp ? (1 << tmp) : 0;
tmp = read1(TYP_BUFFER_WRITE_TIMEOUT_OFFSET);
cfi->system_interface_info.typ_buffer_write_timeout = tmp ? (1 << tmp) : 0;
tmp = read1(TYP_BLOCK_ERASE_TIMEOUT_OFFSET);
cfi->system_interface_info.typ_block_erase_timeout = tmp ? (1 << tmp) : 0;
tmp = read1(TYP_CHIP_ERASE_TIMEOUT_OFFSET);
cfi->system_interface_info.typ_chip_erase_timeout = tmp ? (1 << tmp) : 0;
tmp = read1(MAX_SINGLE_WRITE_TIMEOUT_OFFSET);
cfi->system_interface_info.max_single_write_timeout =
(tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_single_write_timeout;
tmp = read1(MAX_BUFFER_WRITE_TIMEOUT_OFFSET);
cfi->system_interface_info.max_buffer_write_timeout =
(tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_buffer_write_timeout;
tmp = read1(MAX_BLOCK_ERASE_TIMEOUT_OFFSET);
cfi->system_interface_info.max_block_erase_timeout =
(tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_block_erase_timeout;
tmp = read1(MAX_CHIP_ERASE_TIMEOUT_OFFSET);
cfi->system_interface_info.max_chip_erase_timeout =
(tmp ? (1 << tmp) : 0) * cfi->system_interface_info.typ_chip_erase_timeout;
/* Device geometry - see Table 8 in [1] */
/* TODO: Add out of range check */
cfi->device_geometry.device_size = 1 << read1(DEVICE_SIZE_OFFSET);
cfi->device_geometry.device_interface = read2(FLASH_DEVICE_INTERFACE_OFFSET);
/* TODO: Add out of range check */
cfi->device_geometry.max_bytes_write = 1 << read2(MAX_BYTES_WRITE_OFFSET);
tmp = cfi->device_geometry.number_of_erase_regions = read1(NUMBER_OF_ERASE_REGIONS_OFFSET);
cfi->device_geometry.erase_block_regions = malloc( tmp * sizeof (cfi_erase_block_region_t) );
if (!cfi->device_geometry.erase_block_regions) {
write1( 0, CFI_CMD_READ_ARRAY1 );
return -2; /* out of memory */
}
{
int a;
int i;
for (i = 0, a = ERASE_BLOCK_REGION_OFFSET; i < tmp; i++, a += 4) {
uint32_t y = read2(a);
uint32_t z = read2(a + 2) << 8;
if (z == 0)
z = 128;
cfi->device_geometry.erase_block_regions[i].erase_block_size = z;
cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks = y + 1;
}
}
/* TODO: Intel Primary Algorithm Extended Query Table - see Table 5. in [2] */
/* Read Array */
write1( 0, CFI_CMD_READ_ARRAY1 );
#undef A
#undef D
#undef gD
#undef read1
#undef read2
#undef write1
switch (cfi->device_geometry.device_interface) {
case CFI_INTERFACE_X8:
if (ma != 1)
return -7; /* error in device detection */
(*cfi_array)->cfi_chips[d / 8]->width = 1;
break;
case CFI_INTERFACE_X16:
if (ma != 1)
return -7; /* error in device detection */
(*cfi_array)->cfi_chips[d / 8]->width = 2;
d += 8;
break;
case CFI_INTERFACE_X8_X16:
if (ma != 1 && ma != 2)
return -7; /* error in device detection */
(*cfi_array)->cfi_chips[d / 8]->width = 2 / ma;
if (ma == 1)
d += 8;
break;
case CFI_INTERFACE_X32:
if (ma != 1)
return -7; /* error in device detection */
(*cfi_array)->cfi_chips[d / 8]->width = 4;
d += 24;
break;
case CFI_INTERFACE_X16_X32:
if (ma != 1 && ma != 2)
return -7; /* error in device detection */
(*cfi_array)->cfi_chips[d / 8]->width = 4 / ma;
if (ma == 1)
d += 24;
else
d += 8;
break;
default:
return -7; /* error in device detection */
}
}
return 0;
}

@ -0,0 +1,205 @@
/*
* $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.
*
* Documentation:
* [1] JEDEC Solid State Technology Association, "Common Flash Interface (CFI)",
* September 1999, Order Number: JESD68
* [2] JEDEC Solid State Technology Association, "Common Flash Interface (CFI) ID Codes",
* September 2001, Order Number: JEP137-A
*
*/
#include "sysdep.h"
#include <stdint.h>
#include <string.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <flash/mic.h>
#include <flash.h>
#include <bus.h>
cfi_array_t *cfi_array = NULL;
extern int jedec_detect( bus_t *bus, uint32_t adr, cfi_array_t **cfi_array );
extern int amd_detect(bus_t *bus, uint32_t adr, cfi_array_t **cfi_array ); //Ajith
void
detectflash( bus_t *bus, uint32_t adr )
{
cfi_query_structure_t *cfi;
const char *s;
if (!bus) {
printf( _("Error: Missing bus driver!\n") );
return;
}
cfi_array_free( cfi_array );
cfi_array = NULL;
bus_prepare( bus );
if (cfi_detect( bus, adr, &cfi_array )) {
cfi_array_free( cfi_array );
cfi_array = NULL;
if (jedec_detect( bus, adr, &cfi_array ) != 0) {
cfi_array_free( cfi_array );
if(amd_detect(bus, adr, &cfi_array ) != 0)
{
cfi_array_free( cfi_array );
cfi_array->bus_width = 1;
cfi_array = NULL;
printf( _("Flash not found!\n") );
return;
}
}
}
cfi = &cfi_array->cfi_chips[0]->cfi;
/* detect CFI capable devices */
/* TODO: Low chip only */
/* see 4.3.2 in [1] */
printf( _("Query identification string:\n") );
/* see section 2 in [2] */
switch (cfi->identification_string.pri_id_code) {
case CFI_VENDOR_NULL:
s = N_("null");
break;
case CFI_VENDOR_INTEL_ECS:
s = N_("Intel/Sharp Extended Command Set");
break;
case CFI_VENDOR_AMD_SCS:
s = N_("AMD/Fujitsu Standard Command Set");
break;
case CFI_VENDOR_INTEL_SCS:
s = N_("Intel Standard Command Set");
break;
case CFI_VENDOR_AMD_ECS:
s = N_("AMD/Fujitsu Extended Command Set");
break;
case CFI_VENDOR_MITSUBISHI_SCS:
s = N_("Mitsubishi Standard Command Set");
break;
case CFI_VENDOR_MITSUBISHI_ECS:
s = N_("Mitsubishi Extended Command Set");
break;
case CFI_VENDOR_SST_PWCS:
s = N_("Page Write Command Set");
break;
default:
s = N_("unknown!!!");
break;
}
printf( _("\tPrimary Algorithm Command Set and Control Interface ID Code: 0x%04X (%s)\n"), cfi->identification_string.pri_id_code, _(s) );
switch (cfi->identification_string.alt_id_code) {
case CFI_VENDOR_NULL:
s = N_("null");
break;
case CFI_VENDOR_INTEL_ECS:
s = N_("Intel/Sharp Extended Command Set");
break;
case CFI_VENDOR_AMD_SCS:
s = N_("AMD/Fujitsu Standard Command Set");
break;
case CFI_VENDOR_INTEL_SCS:
s = N_("Intel Standard Command Set");
break;
case CFI_VENDOR_AMD_ECS:
s = N_("AMD/Fujitsu Extended Command Set");
break;
case CFI_VENDOR_MITSUBISHI_SCS:
s = N_("Mitsubishi Standard Command Set");
break;
case CFI_VENDOR_MITSUBISHI_ECS:
s = N_("Mitsubishi Extended Command Set");
break;
case CFI_VENDOR_SST_PWCS:
s = N_("Page Write Command Set");
break;
default:
s = N_("unknown!!!");
break;
}
printf( _("\tAlternate Algorithm Command Set and Control Interface ID Code: 0x%04X (%s)\n"), cfi->identification_string.alt_id_code, _(s) );
/* see 4.3.3 in [1] */
printf( _("Query system interface information:\n") );
printf( _("\tVcc Logic Supply Minimum Write/Erase or Write voltage: %d mV\n"), cfi->system_interface_info.vcc_min_wev );
printf( _("\tVcc Logic Supply Maximum Write/Erase or Write voltage: %d mV\n"), cfi->system_interface_info.vcc_max_wev );
printf( _("\tVpp [Programming] Supply Minimum Write/Erase voltage: %d mV\n"), cfi->system_interface_info.vpp_min_wev );
printf( _("\tVpp [Programming] Supply Maximum Write/Erase voltage: %d mV\n"), cfi->system_interface_info.vpp_max_wev );
printf( _("\tTypical timeout per single byte/word program: %d us\n"), cfi->system_interface_info.typ_single_write_timeout );
printf( _("\tTypical timeout for maximum-size multi-byte program: %d us\n"), cfi->system_interface_info.typ_buffer_write_timeout );
printf( _("\tTypical timeout per individual block erase: %d ms\n"), cfi->system_interface_info.typ_block_erase_timeout );
printf( _("\tTypical timeout for full chip erase: %d ms\n"), cfi->system_interface_info.typ_chip_erase_timeout );
printf( _("\tMaximum timeout for byte/word program: %d us\n"), cfi->system_interface_info.max_single_write_timeout );
printf( _("\tMaximum timeout for multi-byte program: %d us\n"), cfi->system_interface_info.max_buffer_write_timeout );
printf( _("\tMaximum timeout per individual block erase: %d ms\n"), cfi->system_interface_info.max_block_erase_timeout );
printf( _("\tMaximum timeout for chip erase: %d ms\n"), cfi->system_interface_info.max_chip_erase_timeout );
/* see 4.3.4 in [1] */
printf( _("Device geometry definition:\n") );
printf( _("\tDevice Size: %d B (%d KiB, %d MiB)\n"),
cfi->device_geometry.device_size,
cfi->device_geometry.device_size / 1024,
cfi->device_geometry.device_size / (1024 * 1024) );
/* see section 4 in [2] */
switch (cfi->device_geometry.device_interface) {
case CFI_INTERFACE_X8:
s = N_("x8");
break;
case CFI_INTERFACE_X16:
s = N_("x16");
break;
case CFI_INTERFACE_X8_X16:
s = N_("x8/x16");
break;
case CFI_INTERFACE_X32:
s = N_("x32");
break;
case CFI_INTERFACE_X16_X32:
s = N_("x16/x32");
break;
default:
s = N_("unknown!!!");
break;
}
printf( _("\tFlash Device Interface Code description: 0x%04X (%s)\n"), cfi->device_geometry.device_interface, _(s) );
printf( _("\tMaximum number of bytes in multi-byte program: %d\n"), cfi->device_geometry.max_bytes_write );
printf( _("\tNumber of Erase Block Regions within device: %d\n"), cfi->device_geometry.number_of_erase_regions );
printf( _("\tErase Block Region Information:\n") );
{
int i;
for (i = 0; i < cfi->device_geometry.number_of_erase_regions; i++) {
printf( _("\t\tRegion %d:\n"), i );
printf( _("\t\t\tErase Block Size: %d B (%d KiB)\n"),
cfi->device_geometry.erase_block_regions[i].erase_block_size,
cfi->device_geometry.erase_block_regions[i].erase_block_size / 1024 );
printf( _("\t\t\tNumber of Erase Blocks: %d\n"), cfi->device_geometry.erase_block_regions[i].number_of_erase_blocks );
}
}
}

@ -0,0 +1,380 @@
/*
* $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 "sysdep.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <flash/mic.h>
#include <flash.h>
#include <bus.h>
static int intel_flash_erase_block( cfi_array_t *cfi_array, uint32_t adr );
static int intel_flash_unlock_block( cfi_array_t *cfi_array, uint32_t adr );
static int intel_flash_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data );
static int intel_flash_erase_block32( cfi_array_t *cfi_array, uint32_t adr );
static int intel_flash_unlock_block32( cfi_array_t *cfi_array, uint32_t adr );
static int intel_flash_program32( cfi_array_t *cfi_array, uint32_t adr, uint32_t data );
/* autodetect, we can handle this chip */
static int
intel_flash_autodetect32( cfi_array_t *cfi_array )
{
bus_area_t area;
if (bus_area( cfi_array->bus, cfi_array->address, &area ) != 0)
return 0;
return ((cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_INTEL_ECS)
|| (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_INTEL_SCS))
&& (area.width == 32);
}
static int
intel_flash_autodetect( cfi_array_t *cfi_array )
{
bus_area_t area;
if (bus_area( cfi_array->bus, cfi_array->address, &area ) != 0)
return 0;
return ((cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_INTEL_ECS)
|| (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_INTEL_SCS))
&& (area.width == 16);
}
static int
intel_flash_autodetect8( cfi_array_t *cfi_array )
{
bus_area_t area;
if (bus_area( cfi_array->bus, cfi_array->address, &area ) != 0)
return 0;
return ((cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_INTEL_ECS)
|| (cfi_array->cfi_chips[0]->cfi.identification_string.pri_id_code == CFI_VENDOR_INTEL_SCS))
&& (area.width == 8);
}
static void
_intel_flash_print_info( cfi_array_t *cfi_array, int o )
{
uint32_t mid, cid;
bus_t *bus = cfi_array->bus;
mid = (bus_read( bus, cfi_array->address + (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( bus, cfi_array->address + (0x01 << o) ) & 0xFFFF);
switch (cid) {
case 0x0016:
printf( "28F320J3A\n" );
break;
case 0x0017:
printf( "28F640J3A\n" );
break;
case 0x0018:
printf( "28F128J3A\n" );
break;
case 0x001D:
printf( "28F256J3A\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;
case 0x880B:
printf( "GE28F640L18T\n" );
break;
case 0x880C:
printf( "GE28F128L18T\n" );
break;
case 0x880D:
printf( "GE28F256L18T\n" );
break;
case 0x880E:
printf( "GE28F640L18B\n" );
break;
case 0x880F:
printf( "GE28F128L18B\n" );
break;
case 0x8810:
printf( "GE28F256L18B\n" );
break;
default:
printf( _("Unknown (0x%02X)!\n"), cid );
break;
}
/* Read Array */
bus_write( bus, cfi_array->address + (0 << o), 0x00FF00FF );
}
static void
intel_flash_print_info( cfi_array_t *cfi_array )
{
int o = 1;
bus_t *bus = cfi_array->bus;
/* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
/* TODO */
/* Clear Status Register */
bus_write( bus, cfi_array->address + (0 << o), 0x0050 );
/* Read Identifier Command */
bus_write( bus, cfi_array->address + (0 << 0), 0x0090 );
_intel_flash_print_info( cfi_array, o );
}
static void
intel_flash_print_info32( cfi_array_t *cfi_array )
{
int o = 2;
bus_t *bus = cfi_array->bus;
/* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
/* TODO */
/* Clear Status Register */
bus_write( bus, cfi_array->address + (0 << o), 0x00500050 );
/* Read Identifier Command */
bus_write( bus, cfi_array->address + (0 << 0), 0x00900090 );
_intel_flash_print_info( cfi_array, o );
}
static int
intel_flash_erase_block( cfi_array_t *cfi_array, uint32_t adr )
{
uint16_t sr;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
bus_write( bus, adr, CFI_INTEL_CMD_BLOCK_ERASE );
bus_write( bus, adr, CFI_INTEL_CMD_CONFIRM );
while (!((sr = bus_read( bus, cfi_array->address ) & 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 FLASH_ERROR_INVALID_COMMAND_SEQUENCE;
case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_VPEN_ERROR:
printf( _("flash: low vpen\n") );
return FLASH_ERROR_LOW_VPEN;
case CFI_INTEL_SR_ERASE_ERROR | CFI_INTEL_SR_BLOCK_LOCKED:
printf( _("flash: block locked\n") );
return FLASH_ERROR_BLOCK_LOCKED;
default:
break;
}
return FLASH_ERROR_UNKNOWN;
}
static int
intel_flash_unlock_block( cfi_array_t *cfi_array, uint32_t adr )
{
uint16_t sr;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
bus_write( bus, adr, CFI_INTEL_CMD_LOCK_SETUP );
bus_write( bus, adr, CFI_INTEL_CMD_UNLOCK_BLOCK );
while (!((sr = bus_read( bus, cfi_array->address ) & 0xFE) & CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
if (sr != CFI_INTEL_SR_READY) {
printf( _("flash: unknown error while unblocking\n") );
return FLASH_ERROR_UNKNOWN;
} else
return 0;
}
static int
intel_flash_program( cfi_array_t *cfi_array, uint32_t adr, uint32_t data )
{
uint16_t sr;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
bus_write( bus, adr, CFI_INTEL_CMD_PROGRAM1 );
bus_write( bus, adr, data );
while (!((sr = bus_read( bus, cfi_array->address ) & 0xFE) & CFI_INTEL_SR_READY)) ; /* TODO: add timeout */
if (sr != CFI_INTEL_SR_READY) {
printf( _("flash: unknown error while programming\n") );
return FLASH_ERROR_UNKNOWN;
} else
return 0;
}
static int
intel_flash_erase_block32( cfi_array_t *cfi_array, uint32_t adr )
{
uint32_t sr;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address, (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) | CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
bus_write( bus, adr, (CFI_INTEL_CMD_BLOCK_ERASE << 16) | CFI_INTEL_CMD_BLOCK_ERASE );
bus_write( bus, adr, (CFI_INTEL_CMD_CONFIRM << 16) | CFI_INTEL_CMD_CONFIRM );
while (((sr = bus_read( bus, cfi_array->address ) & 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 FLASH_ERROR_UNKNOWN;
} else
return 0;
}
static int
intel_flash_unlock_block32( cfi_array_t *cfi_array, uint32_t adr )
{
uint32_t sr;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address, (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) | CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
bus_write( bus, adr, (CFI_INTEL_CMD_LOCK_SETUP << 16) | CFI_INTEL_CMD_LOCK_SETUP );
bus_write( bus, adr, (CFI_INTEL_CMD_UNLOCK_BLOCK << 16) | CFI_INTEL_CMD_UNLOCK_BLOCK );
while (((sr = bus_read( bus, cfi_array->address ) & 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 FLASH_ERROR_UNKNOWN;
} else
return 0;
}
static int
intel_flash_program32( cfi_array_t *cfi_array, uint32_t adr, uint32_t data )
{
uint32_t sr;
bus_t *bus = cfi_array->bus;
bus_write( bus, cfi_array->address, (CFI_INTEL_CMD_CLEAR_STATUS_REGISTER << 16) | CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
bus_write( bus, adr, (CFI_INTEL_CMD_PROGRAM1 << 16) | CFI_INTEL_CMD_PROGRAM1 );
bus_write( bus, adr, data );
while (((sr = bus_read( bus, cfi_array->address ) & 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 FLASH_ERROR_UNKNOWN;
} else
return 0;
}
static void
intel_flash_readarray32( cfi_array_t *cfi_array )
{
/* Read Array */
bus_write( cfi_array->bus, cfi_array->address, 0x00FF00FF );
}
static void
intel_flash_readarray( cfi_array_t *cfi_array )
{
/* Read Array */
bus_write( cfi_array->bus, cfi_array->address, 0x00FF00FF );
}
flash_driver_t intel_32_flash_driver = {
4, /* buswidth */
N_("Intel Standard Command Set"),
N_("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 */
N_("Intel Standard Command Set"),
N_("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,
};
flash_driver_t intel_8_flash_driver = {
1, /* buswidth */
N_("Intel Standard Command Set"),
N_("supported: 28Fxxxx, 1 x 8 bit"),
intel_flash_autodetect8,
intel_flash_print_info,
intel_flash_erase_block,
intel_flash_unlock_block,
intel_flash_program,
intel_flash_readarray,
};

@ -0,0 +1,490 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <unistd.h>
#include <flash.h>
#include <bus.h>
/* Manufacturers */
#define MANUFACTURER_AMD 0x0001
#define MANUFACTURER_ATMEL 0x001F
#define MANUFACTURER_FUJITSU 0x0004
#define MANUFACTURER_ST 0x0020
#define MANUFACTURER_SST 0x00BF
#define MANUFACTURER_TOSHIBA 0x0098
#define MANUFACTURER_MX 0x00C2
/* AMD */
#define AM29F800BB 0x2258
#define AM29F800BT 0x22D6
#define AM29LV800BB 0x225B
#define AM29LV800BT 0x22DA
#define AM29LV160DT 0x22C4
#define AM29LV160DB 0x2249
#define AM29BDS323D 0x22D1
#define AM29BDS643D 0x227E
#define AM29LV040B 0x004F
/* Atmel */
#define AT49xV16x 0x00C0
#define AT49xV16xT 0x00C2
/* Fujitsu */
#define MBM29LV160TE 0x22C4
#define MBM29LV160BE 0x2249
#define MBM29LV800BB 0x225B
/* ST - www.st.com */
#define M29W800T 0x00D7
#define M29W160DT 0x22C4
#define M29W160DB 0x2249
/* SST */
#define SST39LF800 0x2781
#define SST39LF160 0x2782
/* Toshiba */
#define TC58FVT160 0x00C2
#define TC58FVB160 0x0043
/* MX */
#define MX29LV400T 0x22B9
/* Autoselect methods */
#define AUTOSELECT_M1 0
#define AUTOSELECT_M2 1
#define AUTOSELECT_NUM 2
struct mtd_erase_region_info {
u_int32_t offset; /* At which this region starts, from the beginning of the MTD */
u_int32_t erasesize; /* For this region */
u_int32_t numblocks; /* Number of blocks of erasesize in this region */
};
struct amd_flash_info {
const int mfr_id;
const int dev_id;
const char *name;
const long size;
const u_int8_t interface_width;
const int as_method;
const int numeraseregions;
const struct mtd_erase_region_info regions[4];
};
static const struct amd_flash_info table[] = {
{
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29LV160DT,
.name = "AMD AM29LV160DT",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29LV160DB,
.name = "AMD AM29LV160DB",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
}
}, {
.mfr_id = MANUFACTURER_TOSHIBA,
.dev_id = TC58FVT160,
.name = "Toshiba TC58FVT160",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_FUJITSU,
.dev_id = MBM29LV160TE,
.name = "Fujitsu MBM29LV160TE",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_TOSHIBA,
.dev_id = TC58FVB160,
.name = "Toshiba TC58FVB160",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
}
}, {
.mfr_id = MANUFACTURER_FUJITSU,
.dev_id = MBM29LV160BE,
.name = "Fujitsu MBM29LV160BE",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29LV800BB,
.name = "AMD AM29LV800BB",
.size = 0x00100000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29F800BB,
.name = "AMD AM29F800BB",
.size = 0x00100000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29LV800BT,
.name = "AMD AM29LV800BT",
.size = 0x00100000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29F800BT,
.name = "AMD AM29F800BT",
.size = 0x00100000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29LV800BB,
.name = "AMD AM29LV800BB",
.size = 0x00100000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_FUJITSU,
.dev_id = MBM29LV800BB,
.name = "Fujitsu MBM29LV800BB",
.size = 0x00100000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 15 }
}
}, {
.mfr_id = MANUFACTURER_ST,
.dev_id = M29W800T,
.name = "ST M29W800T",
.size = 0x00100000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 15 },
{ .offset = 0x0F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x0F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x0FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_ST,
.dev_id = M29W160DT,
.name = "ST M29W160DT",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x1F0000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x1F8000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x1FC000, .erasesize = 0x04000, .numblocks = 1 }
}
}, {
.mfr_id = MANUFACTURER_ST,
.dev_id = M29W160DB,
.name = "ST M29W160DB",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x04000, .numblocks = 1 },
{ .offset = 0x004000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x008000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29BDS323D,
.name = "AMD AM29BDS323D",
.size = 0x00400000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 3,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 48 },
{ .offset = 0x300000, .erasesize = 0x10000, .numblocks = 15 },
{ .offset = 0x3f0000, .erasesize = 0x02000, .numblocks = 8 },
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29BDS643D,
.name = "AMD AM29BDS643D",
.size = 0x00800000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 3,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 96 },
{ .offset = 0x600000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x7f0000, .erasesize = 0x02000, .numblocks = 8 },
}
}, {
.mfr_id = MANUFACTURER_ATMEL,
.dev_id = AT49xV16x,
.name = "Atmel AT49xV16x",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 2,
.regions = {
{ .offset = 0x000000, .erasesize = 0x02000, .numblocks = 8 },
{ .offset = 0x010000, .erasesize = 0x10000, .numblocks = 31 }
}
}, {
.mfr_id = MANUFACTURER_ATMEL,
.dev_id = AT49xV16xT,
.name = "Atmel AT49xV16xT",
.size = 0x00200000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 2,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 31 },
{ .offset = 0x1F0000, .erasesize = 0x02000, .numblocks = 8 }
}
}, {
.mfr_id = MANUFACTURER_MX,
.dev_id = MX29LV400T,
.name = "MX 29LV400T",
.size = 0x0080000,
.interface_width = CFI_INTERFACE_X16, /* correct default? */
.as_method = AUTOSELECT_M1,
.numeraseregions = 4,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 7 },
{ .offset = 0x070000, .erasesize = 0x08000, .numblocks = 1 },
{ .offset = 0x078000, .erasesize = 0x02000, .numblocks = 2 },
{ .offset = 0x07c000, .erasesize = 0x04000, .numblocks = 1 },
}
}, {
.mfr_id = MANUFACTURER_AMD,
.dev_id = AM29LV040B,
.name = "AMD AM29LV040B",
.size = 0x0080000,
.interface_width = CFI_INTERFACE_X8, /* checked, ok */
.as_method = AUTOSELECT_M2,
.numeraseregions = 1,
.regions = {
{ .offset = 0x000000, .erasesize = 0x10000, .numblocks = 8 },
}
}
};
int
jedec_detect( bus_t *bus, uint32_t adr, cfi_array_t **cfi_array )
{
/* Temporary containers for manufacturer and device id while
probing with different Autoselect methods. */
int manid_as[AUTOSELECT_NUM], devid_as[AUTOSELECT_NUM];
int manid = 0, devid = 0;
int ba, bw;
int i, j;
cfi_query_structure_t *cfi;
bus_area_t area;
*cfi_array = calloc( 1, sizeof (cfi_array_t) );
if (!*cfi_array)
return -2; /* out of memory */
(*cfi_array)->bus = bus;
(*cfi_array)->address = adr;
if (bus_area( bus, adr, &area ) != 0)
return -8; /* bus width detection failed */
bw = area.width;
if (bw != 8 && bw != 16 && bw != 32)
return -3; /* invalid bus width */
(*cfi_array)->bus_width = ba = bw / 8;
(*cfi_array)->cfi_chips = calloc( 1, sizeof (cfi_chip_t *) );
if (!(*cfi_array)->cfi_chips)
return -2; /* out of memory */
(*cfi_array)->cfi_chips[0] = calloc( 1, sizeof (cfi_chip_t) );
if (!(*cfi_array)->cfi_chips[0])
return -2; /* out of memory */
/* probe device with Autoselect method 1 */
bus_write(bus, adr, 0xf0);
bus_write(bus, adr+0xaaa, 0xaa);
bus_write(bus, adr+0x555, 0x55);
bus_write(bus, adr+0xaaa, 0x90);
manid_as[AUTOSELECT_M1] = bus_read(bus, adr+0);
devid_as[AUTOSELECT_M1] = bus_read(bus, adr+2);
bus_write(bus, adr, 0xf0);
/* probe device with Autoselect method 2 */
bus_write(bus, adr, 0xf0);
bus_write(bus, adr+0x555, 0xaa);
bus_write(bus, adr+0x2aa, 0x55);
bus_write(bus, adr+0x555, 0x90);
manid_as[AUTOSELECT_M2] = bus_read(bus, adr+0);
devid_as[AUTOSELECT_M2] = bus_read(bus, adr+1);
bus_write(bus, adr, 0xf0);
for(i=0 ; i<sizeof(table)/sizeof(struct amd_flash_info) ; i++) {
/* compare manufacturer and device id based on the result
of the device's Autoselect method */
manid = manid_as[table[i].as_method];
devid = devid_as[table[i].as_method];
if(manid==table[i].mfr_id && devid==table[i].dev_id) break;
}
fprintf(stderr, "dev ID=%04x man ID=%04x\n", devid, manid);
if(i==sizeof(table)/sizeof(struct amd_flash_info))
return -4;
cfi = &(*cfi_array)->cfi_chips[0]->cfi;
cfi->identification_string.pri_id_code = CFI_VENDOR_AMD_SCS;
cfi->identification_string.pri_vendor_tbl = NULL;
cfi->identification_string.alt_id_code = 0;
cfi->identification_string.alt_vendor_tbl = NULL;
cfi->device_geometry.device_size = table[i].size;
/* annotate chip width */
cfi->device_geometry.device_interface = table[i].interface_width;
switch (table[i].interface_width) {
case CFI_INTERFACE_X8:
(*cfi_array)->cfi_chips[0]->width = 1;
break;
case CFI_INTERFACE_X16:
(*cfi_array)->cfi_chips[0]->width = 2;
break;
case CFI_INTERFACE_X8_X16:
fprintf(stderr, "Warning: Unsupported interface geometry %s, falling back to %s\n", "CFI_INTERFACE_X8_X16", "CFI_INTERFACE_X16");
(*cfi_array)->cfi_chips[0]->width = 2;
cfi->device_geometry.device_interface = CFI_INTERFACE_X16;
break;
case CFI_INTERFACE_X32:
(*cfi_array)->cfi_chips[0]->width = 4;
break;
case CFI_INTERFACE_X16_X32:
fprintf(stderr, "Warning: Unsupported interface geometry %s, falling back to %s\n", "CFI_INTERFACE_X16_X32", "CFI_INTERFACE_X32");
(*cfi_array)->cfi_chips[0]->width = 4;
cfi->device_geometry.device_interface = CFI_INTERFACE_X32;
break;
default:
/* unsupported interface geometry */
fprintf(stderr, "Error: Unsupported interface geometry %d, bailing out\n", table[i].interface_width);
(*cfi_array)->cfi_chips[0]->width = 1;
cfi->device_geometry.device_interface = CFI_INTERFACE_X8;
return -5;
break;
}
cfi->device_geometry.number_of_erase_regions = table[i].numeraseregions;
cfi->device_geometry.erase_block_regions =
malloc( cfi->device_geometry.number_of_erase_regions * sizeof (cfi_erase_block_region_t) );
if (!cfi->device_geometry.erase_block_regions)
return -2; /* out of memory */
for(j=0;j<cfi->device_geometry.number_of_erase_regions; j++) {
cfi->device_geometry.erase_block_regions[j].erase_block_size =
table[i].regions[j].erasesize;
cfi->device_geometry.erase_block_regions[j].number_of_erase_blocks =
table[i].regions[j].numblocks;
}
fprintf(stderr, "Found %s flash, size = %li bytes.\n", table[i].name, table[i].size);
return 0;
}

@ -34,7 +34,7 @@
#include <string.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <std/mic.h>
#include <flash/mic.h>
#include "bus.h"
#include "flash.h"

@ -43,7 +43,7 @@
#include <tap.h>
#include <state.h>
#include <brux/cmd.h>
#include <cmd.h>
#include "svf.h"
#include "svf_bison.h"

@ -34,7 +34,7 @@
#include "generic.h"
#include <brux/cmd.h>
#include <cmd.h>
int
generic_connect( char *params[], cable_t *cable )

@ -39,7 +39,7 @@
#include "generic.h"
#include <brux/cmd.h>
#include <cmd.h>
#define SYSCON_BASE 0x80930000
#define SYSCON_DEVICE_CONFIG 0x80

@ -39,7 +39,7 @@
#include "generic.h"
#include <brux/cmd.h>
#include <cmd.h>
/*
* Bit <-> pin mapping of an original Wiggler

@ -27,7 +27,7 @@
#include <string.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <std/mic.h>
#include <flash/mic.h>
#include "bus.h"
#include "flash.h"

Loading…
Cancel
Save