2003-06-02 Marcel Telka <marcel@telka.sk>

* flash/cfi.c: New file. Moved from jtag module (src/flash/cfi.c).
	* flash/amd.c: New file. Moved from jtag module (src/flash/amd.c).
	* flash/intel.c: New file. Moved from jtag module (src/flash/intel.c).

	* autogen.sh: New file.
	* configure.ac: Ditto.
	* Makefile.am: Ditto.


git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@455 b68d4a1b-bc3d-0410-92ed-d4ac073336b7
master
Marcel Telka 22 years ago
parent 84e187b996
commit 977d3d3a20

@ -0,0 +1,8 @@
.deps
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.log
config.status
configure

@ -0,0 +1 @@
Marcel Telka <marcel@telka.sk>

@ -0,0 +1,10 @@
2003-06-02 Marcel Telka <marcel@telka.sk>
* flash/cfi.c: New file. Moved from jtag module (src/flash/cfi.c).
* flash/amd.c: New file. Moved from jtag module (src/flash/amd.c).
* flash/intel.c: New file. Moved from jtag module (src/flash/intel.c).
* autogen.sh: New file.
* configure.ac: Ditto.
* Makefile.am: Ditto.

@ -0,0 +1,31 @@
#
# $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 $(top_srcdir)/../Makefile.rules
noinst_LIBRARIES = libbrux.a
libbrux_a_SOURCES = \
flash/cfi.c \
flash/amd.c \
flash/intel.c

@ -0,0 +1,36 @@
#!/bin/sh
#
# $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.
#
if autoreconf -i -s -v -f ; then
echo
echo "autoreconf done."
echo
else
echo
echo "autoreconf failed."
echo
exit 1
fi
./configure --enable-maintainer-mode

@ -0,0 +1,64 @@
#
# $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.
#
AC_INIT(libbrux,0.1)
AC_PREREQ(2.54)
AC_CONFIG_AUX_DIR(../tools)
AM_INIT_AUTOMAKE
AC_CONFIG_FILES(
Makefile
)
AM_MAINTAINER_MODE
AC_GNU_SOURCE
AC_PROG_CC
AC_PROG_RANLIB
AC_ARG_WITH(include,
AC_HELP_STRING([--with-include=PATH], [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 not found.])
fi
CPPFLAGS="$CPPFLAGS -I$openwince_includes_path -I$openwince_includes_path/device -I$openwince_includes_path/arm"
CFLAGS="$CFLAGS -Wall"
CPPFLAGS="$CPPFLAGS -I\$(top_srcdir)/.. -I\$(top_srcdir)/../include"
AC_OUTPUT

@ -0,0 +1,253 @@
/*
* $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 <config.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.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( bus_t *bus, uint32_t adr );
static int amd_flash_unlock_block( bus_t *bus, uint32_t adr );
static int amd_flash_program( bus_t *bus, uint32_t adr, uint32_t data );
static void amd_flash_read_array( bus_t *bus );
/* autodetect, we can handle this chip */
static int
amd_flash_autodetect( bus_t *bus, 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
*/
#if 0
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;
}
#endif /* 0 */
/*
* 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)) /* 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;
}
#if 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);
}
#endif /* 0 */
static void
amd_flash_print_info( bus_t *bus )
{
int o = 2;
int mid, cid, prot;
bus_write( bus, 0x0555 << o, 0x00aa00aa ); /* autoselect p29 */
bus_write( bus, 0x02aa << o, 0x00550055 );
bus_write( bus, 0x0555 << o, 0x00900090 );
mid = bus_read( bus, 0x00 << o ) & 0xFFFF;
cid = bus_read( bus, 0x01 << o ) & 0xFFFF;
prot = bus_read( bus, 0x02 << o ) & 0xFF;
amd_flash_read_array( bus ); /* 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( bus_t *bus, uint32_t adr )
{
int o = 2;
printf("flash_erase_block 0x%08X\n", adr);
/* printf("protected: %d\n", amdisprotected(ps, adr)); */
bus_write( bus, 0x0555 << o, 0x00aa00aa ); /* autoselect p29, sector erase */
bus_write( bus, 0x02aa << o, 0x00550055 );
bus_write( bus, 0x0555 << o, 0x00800080 );
bus_write( bus, 0x0555 << o, 0x00aa00aa );
bus_write( bus, 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( bus ); /* AMD reset */
return 0;
}
printf( "flash_erase_block 0x%08X FAILED\n", adr );
/* Read Array */
amd_flash_read_array( bus ); /* AMD reset */
return CFI_INTEL_ERROR_UNKNOWN;
}
static int
amd_flash_unlock_block( bus_t *bus, uint32_t adr )
{
printf( "flash_unlock_block 0x%08X IGNORE\n", adr );
return 0;
}
static int
amd_flash_program( bus_t *bus, 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( bus, 0x0555 << o, 0x00aa00aa ); /* autoselect p29, program */
bus_write( bus, 0x02aa << o, 0x00550055 );
bus_write( bus, 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( bus_t *bus )
{
/* Read Array */
bus_write( bus, 0x0, 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_autodetect,
amd_flash_print_info,
amd_flash_erase_block,
amd_flash_unlock_block,
amd_flash_program,
amd_flash_read_array,
};

@ -0,0 +1,253 @@
/*
* $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 <stdint.h>
#include <stdlib.h>
#include <flash/cfi.h>
#include "cfi.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 )
{
int bw; /* bus width */
int d; /* data offset */
int ba; /* bus width address multiplier */
int ma; /* flash mode address multiplier */
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;
bw = bus_width( bus, adr );
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;
ma = 1;
/* detect CFI capable devices - see Table 1 in [1] */
write1( CFI_CMD_QUERY_OFFSET, CFI_CMD_QUERY );
if (read1(CFI_QUERY_ID_OFFSET) != 'Q') {
write1( 0, CFI_CMD_READ_ARRAY1 );
return -4; /* CFI not detected (Q) */
}
for (; ma <= 4; ma *= 2)
if (read1(CFI_QUERY_ID_OFFSET + 1) == 'R')
break;
if (ma > 4) {
write1( 0, CFI_CMD_READ_ARRAY1 );
return -5; /* CFI not detected (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,310 @@
/*
* $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 <config.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <flash/cfi.h>
#include <flash/intel.h>
#include <std/mic.h>
#include "flash.h"
#include "bus.h"
static int intel_flash_erase_block( bus_t *bus, uint32_t adr );
static int intel_flash_unlock_block( bus_t *bus, uint32_t adr );
static int intel_flash_program( bus_t *bus, uint32_t adr, uint32_t data );
static int intel_flash_erase_block32( bus_t *bus, uint32_t adr );
static int intel_flash_unlock_block32( bus_t *bus, uint32_t adr );
static int intel_flash_program32( bus_t *bus, uint32_t adr, uint32_t data );
/* autodetect, we can handle this chip */
static int
intel_flash_autodetect32( bus_t *bus, cfi_query_structure_t *cfi )
{
return (cfi->identification_string.pri_id_code == CFI_VENDOR_INTEL_ECS) && (bus_width( bus, 0 ) == 32);
}
static int
intel_flash_autodetect( bus_t *bus, cfi_query_structure_t *cfi )
{
return (cfi->identification_string.pri_id_code == CFI_VENDOR_INTEL_ECS) && (bus_width( bus, 0 ) == 16);
}
static void
_intel_flash_print_info( bus_t *bus, int o )
{
uint32_t mid, cid;
mid = (bus_read( bus, 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, 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( bus, 0 << o, 0x00FF00FF );
}
static void
intel_flash_print_info( bus_t *bus )
{
int o = 1;
/* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
/* TODO */
/* Clear Status Register */
bus_write( bus, 0 << o, 0x0050 );
/* Read Identifier Command */
bus_write( bus, 0 << 0, 0x0090 );
_intel_flash_print_info( bus, o );
}
static void
intel_flash_print_info32( bus_t *bus )
{
int o = 2;
/* Intel Primary Algorithm Extended Query Table - see Table 5. in [3] */
/* TODO */
/* Clear Status Register */
bus_write( bus, 0 << o, 0x00500050 );
/* Read Identifier Command */
bus_write( bus, 0 << 0, 0x00900090 );
_intel_flash_print_info( bus, o );
}
static int
intel_flash_erase_block( bus_t *bus, uint32_t adr )
{
uint16_t sr;
bus_write( bus, 0, 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, 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( bus_t *bus, uint32_t adr )
{
uint16_t sr;
bus_write( bus, 0, 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, 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( bus_t *bus, uint32_t adr, uint32_t data )
{
uint16_t sr;
bus_write( bus, 0, CFI_INTEL_CMD_CLEAR_STATUS_REGISTER );
bus_write( bus, adr, CFI_INTEL_CMD_PROGRAM1 );
bus_write( bus, adr, data );
while (!((sr = bus_read( bus, 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( bus_t *bus, uint32_t adr )
{
uint32_t sr;
bus_write( bus, 0, (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, 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( bus_t *bus, uint32_t adr )
{
uint32_t sr;
bus_write( bus, 0, (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, 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( bus_t *bus, uint32_t adr, uint32_t data )
{
uint32_t sr;
bus_write( bus, 0, (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, 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( bus_t *bus )
{
/* Read Array */
bus_write( bus, 0, 0x00FF00FF );
}
static void
intel_flash_readarray( bus_t *bus )
{
/* Read Array */
bus_write( bus, 0, 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,
};
Loading…
Cancel
Save