initial push

This commit is contained in:
Bernd Mueller
2026-06-17 13:44:30 +02:00
commit adfd70813f
372 changed files with 146450 additions and 0 deletions

4
m68k/flashlib/.cvsignore Normal file
View File

@@ -0,0 +1,4 @@
.deps
Makefile
Makefile.in
libbdmflash.a

109
m68k/flashlib/Makefile.am Normal file
View File

@@ -0,0 +1,109 @@
##
## $Id: Makefile.am,v 1.10 2008/09/09 11:48:50 cjohns Exp $
##
## This file is part of a free BDM package
##
## 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.
##
AM_CPPFLAGS = -I$(srcdir)/../libelf/lib -I../libelf/lib \
-I$(srcdir)/../driver -I$(srcdir)/../lib \
-DPREFIX="$(prefix)"
lib_LIBRARIES = libbdmflash.a
include_HEADERS = \
bdmfilt.h \
bdmflash.h \
flash_filter.h \
flash29.h \
flashcfm.h \
flashintelc3.h
libbdmflash_a_SOURCES = \
elf-utils.c \
bdmfilt.c \
bdmflash.c \
flash_filter.c \
flash29.c \
flashcfm.c \
flashintelc3.c
if BUILD_FLASH_PLUGINS
#
# Flash Plug-In Source
#
fpi_source = $(1).c $(1).h
#
# Flash Plug-In Target
#
fpi_target = $(foreach target, $(2), $(1)-$(target).plugin)
#
# Full instruction set range for the Coldfire plus the CPU32.
#
fpi_multilib = \
cpu32 \
5206 \
5206e \
5307 \
5407 \
54455 \
5475
#
# The list of plugins we have.
#
fpi_flash29 = flash29
fpi_flash29_targets = $(fpi_multilib)
fpi_flash29_source = $(call fpi_source, flash29)
fpi_flash29_plugins = $(call fpi_target, flash29, $(fpi_flash29_targets))
fpi_flashcfm = flashcfm
fpi_flashcfm_targets = \
5206 \
5206e \
54455
fpi_flashcfm_source = $(call fpi_source, flashcfm)
fpi_flashcfm_plugins = $(call fpi_target, flashcfm, $(fpi_flashcfm_targets))
fpi_flashintelc3 = flashintelc3
fpi_flashintelc3_targets = $(fpi_multilib)
fpi_flashintelc3_source = $(call fpi_source, flashintelc3)
fpi_flashintelc3_plugins = $(call fpi_target, flashintelc3, $(fpi_flashintelc3_targets))
fpi_plugins = \
$(fpi_flash29_plugins) \
$(fpi_flashcfm_plugins) \
$(fpi_flashintelc3_plugins)
all-local: \
$(fpi_plugins)
$(fpi_flash29_plugins): $(fpi_flash29_source)
$(srcdir)/m68k-bdm-compile-plugin @FLASH_PLUGIN_GCC@ $< $@
$(fpi_flashcfm_plugins): $(fpi_flashcfm_source)
$(srcdir)/m68k-bdm-compile-plugin @FLASH_PLUGIN_GCC@ $< $@
$(fpi_flashintelc3_plugins): $(fpi_flashintelc3_source)
$(srcdir)/m68k-bdm-compile-plugin @FLASH_PLUGIN_GCC@ $< $@
install-data-local: \
$(fpi_plugins)
test -z "$(prefix)/share/m68k-bdm/plugins" || \
mkdir -p "$(prefix)/share/m68k-bdm/plugins"; \
for f in $^; do \
install -m 644 $$f $(prefix)/share/m68k-bdm/plugins/$$f; \
done
clean-local:
rm -f *.plugin
endif
EXTRA_DIST = README $(fpi_plugins)

575
m68k/flashlib/Makefile.in Normal file
View File

@@ -0,0 +1,575 @@
# Makefile.in generated by automake 1.10 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = flashlib
DIST_COMMON = README $(include_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(SHELL) $(top_srcdir)/config/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"
libLIBRARIES_INSTALL = $(INSTALL_DATA)
LIBRARIES = $(lib_LIBRARIES)
ARFLAGS = cru
libbdmflash_a_AR = $(AR) $(ARFLAGS)
libbdmflash_a_LIBADD =
am_libbdmflash_a_OBJECTS = elf-utils.$(OBJEXT) bdmfilt.$(OBJEXT) \
bdmflash.$(OBJEXT) flash_filter.$(OBJEXT) flash29.$(OBJEXT) \
flashcfm.$(OBJEXT) flashintelc3.$(OBJEXT)
libbdmflash_a_OBJECTS = $(am_libbdmflash_a_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(top_builddir)@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libbdmflash_a_SOURCES)
DIST_SOURCES = $(libbdmflash_a_SOURCES)
includeHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(include_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AR = @AR@
AS = @AS@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BDM_SUBDIRS = @BDM_SUBDIRS@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
FLASH_PLUGIN_GCC = @FLASH_PLUGIN_GCC@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBUSB_INCLUDE_DIR = @LIBUSB_INCLUDE_DIR@
LIBUSB_LIB_DIR = @LIBUSB_LIB_DIR@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
flash_plugin_cc = @flash_plugin_cc@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
subdirs = @subdirs@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CPPFLAGS = -I$(srcdir)/../libelf/lib -I../libelf/lib \
-I$(srcdir)/../driver -I$(srcdir)/../lib \
-DPREFIX="$(prefix)"
lib_LIBRARIES = libbdmflash.a
include_HEADERS = \
bdmfilt.h \
bdmflash.h \
flash_filter.h \
flash29.h \
flashcfm.h \
flashintelc3.h
libbdmflash_a_SOURCES = \
elf-utils.c \
bdmfilt.c \
bdmflash.c \
flash_filter.c \
flash29.c \
flashcfm.c \
flashintelc3.c
#
# Flash Plug-In Source
#
@BUILD_FLASH_PLUGINS_TRUE@fpi_source = $(1).c $(1).h
#
# Flash Plug-In Target
#
@BUILD_FLASH_PLUGINS_TRUE@fpi_target = $(foreach target, $(2), $(1)-$(target).plugin)
#
# Full instruction set range for the Coldfire plus the CPU32.
#
@BUILD_FLASH_PLUGINS_TRUE@fpi_multilib = \
@BUILD_FLASH_PLUGINS_TRUE@ cpu32 \
@BUILD_FLASH_PLUGINS_TRUE@ 5206 \
@BUILD_FLASH_PLUGINS_TRUE@ 5206e \
@BUILD_FLASH_PLUGINS_TRUE@ 5307 \
@BUILD_FLASH_PLUGINS_TRUE@ 5407 \
@BUILD_FLASH_PLUGINS_TRUE@ 54455 \
@BUILD_FLASH_PLUGINS_TRUE@ 5475
#
# The list of plugins we have.
#
@BUILD_FLASH_PLUGINS_TRUE@fpi_flash29 = flash29
@BUILD_FLASH_PLUGINS_TRUE@fpi_flash29_targets = $(fpi_multilib)
@BUILD_FLASH_PLUGINS_TRUE@fpi_flash29_source = $(call fpi_source, flash29)
@BUILD_FLASH_PLUGINS_TRUE@fpi_flash29_plugins = $(call fpi_target, flash29, $(fpi_flash29_targets))
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashcfm = flashcfm
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashcfm_targets = \
@BUILD_FLASH_PLUGINS_TRUE@ 5206 \
@BUILD_FLASH_PLUGINS_TRUE@ 5206e \
@BUILD_FLASH_PLUGINS_TRUE@ 54455
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashcfm_source = $(call fpi_source, flashcfm)
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashcfm_plugins = $(call fpi_target, flashcfm, $(fpi_flashcfm_targets))
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashintelc3 = flashintelc3
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashintelc3_targets = $(fpi_multilib)
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashintelc3_source = $(call fpi_source, flashintelc3)
@BUILD_FLASH_PLUGINS_TRUE@fpi_flashintelc3_plugins = $(call fpi_target, flashintelc3, $(fpi_flashintelc3_targets))
@BUILD_FLASH_PLUGINS_TRUE@fpi_plugins = \
@BUILD_FLASH_PLUGINS_TRUE@ $(fpi_flash29_plugins) \
@BUILD_FLASH_PLUGINS_TRUE@ $(fpi_flashcfm_plugins) \
@BUILD_FLASH_PLUGINS_TRUE@ $(fpi_flashintelc3_plugins)
EXTRA_DIST = README $(fpi_plugins)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign flashlib/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --foreign flashlib/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
install-libLIBRARIES: $(lib_LIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)"
@list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f=$(am__strip_dir) \
echo " $(libLIBRARIES_INSTALL) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
$(libLIBRARIES_INSTALL) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
else :; fi; \
done
@$(POST_INSTALL)
@list='$(lib_LIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
p=$(am__strip_dir) \
echo " $(RANLIB) '$(DESTDIR)$(libdir)/$$p'"; \
$(RANLIB) "$(DESTDIR)$(libdir)/$$p"; \
else :; fi; \
done
uninstall-libLIBRARIES:
@$(NORMAL_UNINSTALL)
@list='$(lib_LIBRARIES)'; for p in $$list; do \
p=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(libdir)/$$p'"; \
rm -f "$(DESTDIR)$(libdir)/$$p"; \
done
clean-libLIBRARIES:
-test -z "$(lib_LIBRARIES)" || rm -f $(lib_LIBRARIES)
libbdmflash.a: $(libbdmflash_a_OBJECTS) $(libbdmflash_a_DEPENDENCIES)
-rm -f libbdmflash.a
$(libbdmflash_a_AR) libbdmflash.a $(libbdmflash_a_OBJECTS) $(libbdmflash_a_LIBADD)
$(RANLIB) libbdmflash.a
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bdmfilt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bdmflash.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flash29.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flash_filter.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flashcfm.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flashintelc3.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
install-includeHEADERS: $(include_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(includedir)" || $(MKDIR_P) "$(DESTDIR)$(includedir)"
@list='$(include_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(includeHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(includedir)/$$f'"; \
$(includeHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(includedir)/$$f"; \
done
uninstall-includeHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(include_HEADERS)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(includedir)/$$f'"; \
rm -f "$(DESTDIR)$(includedir)/$$f"; \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
@BUILD_FLASH_PLUGINS_FALSE@all-local:
all-am: Makefile $(LIBRARIES) $(HEADERS) all-local
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
@BUILD_FLASH_PLUGINS_FALSE@install-data-local:
@BUILD_FLASH_PLUGINS_FALSE@clean-local:
clean: clean-am
clean-am: clean-generic clean-libLIBRARIES clean-local mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am: install-data-local install-includeHEADERS
install-dvi: install-dvi-am
install-exec-am: install-libLIBRARIES
install-html: install-html-am
install-info: install-info-am
install-man:
install-pdf: install-pdf-am
install-ps: install-ps-am
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-includeHEADERS uninstall-libLIBRARIES
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS all all-am all-local check check-am clean \
clean-generic clean-libLIBRARIES clean-local ctags distclean \
distclean-compile distclean-generic distclean-tags distdir dvi \
dvi-am html html-am info info-am install install-am \
install-data install-data-am install-data-local install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-includeHEADERS install-info \
install-info-am install-libLIBRARIES install-man install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-includeHEADERS uninstall-libLIBRARIES
@BUILD_FLASH_PLUGINS_TRUE@all-local: \
@BUILD_FLASH_PLUGINS_TRUE@ $(fpi_plugins)
@BUILD_FLASH_PLUGINS_TRUE@$(fpi_flash29_plugins): $(fpi_flash29_source)
@BUILD_FLASH_PLUGINS_TRUE@ $(srcdir)/m68k-bdm-compile-plugin @FLASH_PLUGIN_GCC@ $< $@
@BUILD_FLASH_PLUGINS_TRUE@$(fpi_flashcfm_plugins): $(fpi_flashcfm_source)
@BUILD_FLASH_PLUGINS_TRUE@ $(srcdir)/m68k-bdm-compile-plugin @FLASH_PLUGIN_GCC@ $< $@
@BUILD_FLASH_PLUGINS_TRUE@$(fpi_flashintelc3_plugins): $(fpi_flashintelc3_source)
@BUILD_FLASH_PLUGINS_TRUE@ $(srcdir)/m68k-bdm-compile-plugin @FLASH_PLUGIN_GCC@ $< $@
@BUILD_FLASH_PLUGINS_TRUE@install-data-local: \
@BUILD_FLASH_PLUGINS_TRUE@ $(fpi_plugins)
@BUILD_FLASH_PLUGINS_TRUE@ test -z "$(prefix)/share/m68k-bdm/plugins" || \
@BUILD_FLASH_PLUGINS_TRUE@ mkdir -p "$(prefix)/share/m68k-bdm/plugins"; \
@BUILD_FLASH_PLUGINS_TRUE@ for f in $^; do \
@BUILD_FLASH_PLUGINS_TRUE@ install -m 644 $$f $(prefix)/share/m68k-bdm/plugins/$$f; \
@BUILD_FLASH_PLUGINS_TRUE@ done
@BUILD_FLASH_PLUGINS_TRUE@clean-local:
@BUILD_FLASH_PLUGINS_TRUE@ rm -f *.plugin
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View File

@@ -0,0 +1,33 @@
2008-08-04 Chris Johns <cjohns@users.sourceforge.net>
Plug-in Multilib Map
=========================
This table provides the mapping table for the plugins for the processors in the
Coldfire family. This mapping is based on the instruction set supported by each
processor. A reduction could be made is the FPU was not included. It currently
is.
processor in
5206:
5202, 5204, 5206, 5249, 5250, 5230, 5272
5206e:
5206e, 5207, 5208, 5210a, 5211a, 5211, 5212, 5213, 5214, 5216, 52221,
52223, 52230, 52231, 52231, 52232, 52233, 52234, 52235, 5224, 5225, 5232,
5233, 5234, 5235, 523x, 5270, 5271, 5274, 5274, 5275, 5280, 5281, 5282,
528x
5307:
5307, 5327, 5328, 5329, 532x, 5372, 5373, 537x
5407:
5407
54455:
54450, 54451, 54452, 54453, 54454, 54455
5475:
5470, 5471, 5472, 5473, 5474, 5475, 547x, 5480, 5481, 5482, 5483, 5484,
5485, 548x

113
m68k/flashlib/README Normal file
View File

@@ -0,0 +1,113 @@
README
=========================
2003-12-28 Josef Wolf (jw@raven.inka.de)
2008-06-27 Matthew Riek (matthew.riek@ibiscomputer.com.au)
Flashlib is invoked using bdmctrl. See the *.test script files in
bdm/m68k/utils as examples on how to bootstrap a board and invoke flashlib
for flashing. See also bdm/m68k/utils/README.bdmctrl
Overview
=========================
Following is a rough overview of the flashlib architecture:
filter:
The filter is the main interface to the application. The application
don't really need to know about the flash driver details. Filter's
write_memory() function is the flashing aequivalent of the memcpy()
function. write_memory can write to flash or ram, depending on
the memory region of the write.
driver:
A driver is the implementation of a specific flashing algorithm.
examples are flash29, flashcfm and flashintelc3. If the algorithm
or chip definition for your flash is not supported, you will need
to either add a chip to the chip tables (flash29 and flashintelc3)
or you will have to write a new driver.
chip description:
The chip description describes details of a flash chip. What
information needs to be stored in the description is up to
the driver. Most drivers will probably want to store at least
chip-type and bus-interface. Some flash drivers (such as flashcfm)
don't need a chip description table. Instead, you can configure
the required bits such as flash register offsets using flash_set_var.
flash region:
A flash region describes specific flash chips (depending on the
bus interface). The most important information herein is the
base-address, the length, the driver and the chip description.
plugin:
A driver that can be downloaded and executed on the target.
Note that you don't _need_ plugins. You can use host only mode,
which is very slow, plugins just make flashing much much faster.
A plugin is simply compiling just the driver '.c' file for your
target. For example, If you have a 29 series flash chip on your
board, you would compile flash29.c using your cross compiler
toolchain. Only a few header files are needed (the associated
header file flash29.h, flash_filter.h and stdint.h. note that
when you compile the drivers as a plugin, you must define
HOST_FLASHING as 0. (-DHOST_FLASHING=0 for gcc). You need to
compile with -mpcrel such that the code is relocatable. I have
compiled all current drivers successfully using a m68k-elf gnu
toolchain (version 4.3.0), and with the m68k-rtems4.9 toolchain.
m68k-elf-gcc -DHOST_FLASHING=0 -O2 -Wall -fomit-frame-pointer \
-mpcrel -m<CPU> -Wcast-align -Wstrict-prototypes \
-Wmissing-prototypes -c -o <driver>.plugin <driver>.c
where <driver> is one of flashcfm, flash29 or flashintelc3.
and <CPU> is your 68k arch, such as 5200, 5307, 528x etc.
There is a script provided which compiles the plugins which
takes 2 args, your compiler and your target. eg:
>./compile_plugins m68k-elf-gcc 5200
or
>./compile_plugins m68k-rtems4.9-gcc 5200
you will need to copy the plugins to the working folder you
invoke the bdmctrl scripts from.
host-only mode:
All operations are piped through the BDM interface. This is
extremely slow but very useful for bootstrapping/debugging.
Spend the time to compile plugins for your target
host-assisted mode:
Host downloads plugin. The actual flashing operation is executed
by the plugin. This is the preferred operation mode for flashing
under host-control.
target-only mode:
This mode is for operation without a host. compile filter and
drivers for the target with HOST_FLASHING = 0. This could be used
for boot loaders etc. This option has not been completed, there
are a few FIXME's noted in the flash_filter.c where bit's for
target-only mode remain unimplemented. uses of malloc, free,
strdup may need to be provided with hooks in this mode.
How to write a new driver
=========================
Best is to start with a copy of flash29.[ch]. You should rename the
init_flash29() function and add the new function to the algorithm[] array
in flash_filter.c. Next is to give a new value to the driver_magic string.
This name should be unique because it is used to identify the driver
that belongs to a loaded plugin. Change the download_struct() function to
download the chip description structure of the new driver properly to the
target. Make sure byte orderings and alignment is not messed up while
downloading.

58
m68k/flashlib/bdmfilt.c Normal file
View File

@@ -0,0 +1,58 @@
#include <bdmfilt.h>
#include <errno.h>
#include <string.h>
int bdmlib_load_use_lma=0;
bdmlib_bfilt_t * bdmlib_bfilt=NULL;
int
bdmfilt_wrb_filt(bdmlib_bfilt_t * filt, uint32_t in_adr,
unsigned int size, unsigned char * bl_ptr)
{
int ret, part_ret;
unsigned int part_size;
if (!size) return 0;
while (filt) {
if((in_adr<=filt->end_adr)&&
(in_adr+size-1>=filt->begin_adr)) {
ret = 0;
if(in_adr<filt->begin_adr) {
part_size=filt->begin_adr-in_adr;
part_ret=bdmlib_wrb_filt(filt->next,in_adr,part_size,bl_ptr);
ret+=part_ret;
if(part_ret!=part_size) return ret;
in_adr+=part_size;
bl_ptr+=part_size;
size-=part_size;
}
part_size=filt->end_adr-in_adr+1;
if (part_size>=size) {
part_size=size;
size=0;
} else size-=part_size;
part_ret=filt->wrb_filt(filt,in_adr,part_size,bl_ptr);
ret+=part_ret;
if(part_ret!=part_size) {
dbprintf("write error on filt write, address 0x%lx size %d acknowledged %d errno %d\n",
(long)in_adr, part_size, part_ret, errno);
return ret;
}
in_adr+=part_size;
bl_ptr+=part_size;
if(!size) return ret;
ret+=bdmlib_wrb_filt(filt->next,in_adr,size,bl_ptr);
return ret;
}
filt=filt->next;
}
/* regular memory block write */
if ((ret = bdmlib_write_block(in_adr, size, bl_ptr)) != size) {
dbprintf("write error on block write, written %d acknowledged %d errno %d\n",
size, ret, errno);
return ret;
}
return ret;
}

36
m68k/flashlib/bdmfilt.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* $Id: bdmfilt.h,v 1.4 2008/06/16 00:01:21 cjohns Exp $
*/
#ifndef BDMFILT_H
#define BDMFILT_H
#include <sys/types.h>
#include <stdint.h>
/* support of filtered write for flash programming */
typedef struct bdmlib_bfilt{
struct bdmlib_bfilt *next;
uint32_t begin_adr;
uint32_t end_adr;
int filt_id;
unsigned int flags;
int (*wrb_filt)(struct bdmlib_bfilt *, uint32_t , unsigned int, unsigned char * );
void *info;
void *state;
}bdmlib_bfilt_t;
#define BDMLIB_FILT_ERROR 0x08
#define BDMLIB_FILT_ERASED 0x10
#define BDMLIB_FILT_AUTO 0x20
#define BDMLIB_FILT_FLASH 0x40
int bdmlib_load_use_lma; /* use LMA instead of VMA for load */
bdmlib_bfilt_t * bdmlib_bfilt;
int
bdmlib_wrb_filt(bdmlib_bfilt_t * bdmlib_bfilt, uint32_t in_adr,
unsigned int size, unsigned char * bl_ptr);
#endif /* BDMFILT_H */

989
m68k/flashlib/bdmflash.c Normal file
View File

@@ -0,0 +1,989 @@
/*******************************************************************
Flash programming algorithms for use with BDM flash utility
bdmflash.c - test driver implementation
(C) Copyright 2000-2003 by Pavel Pisa <pisa@waltz.felk.cvut.cz>
This souce is distributed under the Gnu General Public Licence.
See file COPYING for details.
Source could be used under any other license for embeded systems,
but in such case enhancements must be sent to original author.
If some of contributors does not agree with above two lines,
he can delete them and only GPL will apply.
*******************************************************************/
/*
Revision history
2001-01-16 Added experimental support of single 8 bit flash memory
based on Avi Cohen Stuart <astuart@baan.nl> changes
2001-07-10 Added support for amd_29f010 with x8x2 configuration
based on John S. Gwynne <jsg@jsgpc.mrcday.com> changes
Trying to solve x8x2 race condition with shortest
possible code - needs more tests
2001-08-30 Added alg-info for at_49f040 with x8x2 configuration
x8x2 configuration needs more testing, may be broken
2003-05-19 Added initial support for x32 memory configurations.
The x16x2 and x8x4 should work as well. Changes were
motivated by Andrei Smirnov <andrei.s@myrealbox.com>
code, but his small update results in deeper code redesign.
This could enable to support page writes for modern versions
of FLASH memories in future.
2003-11-09 The first attempt to port into Chris's branch
*/
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <BDMlib.h>
#include "bdmfilt.h"
#include "bdmflash.h"
/* predefined flash algorithms metods */
int bdmflash_check_id_x32(const flash_alg_info_t *alg, uint32_t addr, flash_d_t retid[2]);
int bdmflash_prog_x32(const flash_alg_info_t *alg, uint32_t addr, const void *data, long count);
int bdmflash_erase_x32(const flash_alg_info_t *alg, uint32_t addr, long size);
int bdmflash_check_id_x16(const flash_alg_info_t *alg, uint32_t addr, flash_d_t retid[2]);
int bdmflash_prog_x16(const flash_alg_info_t *alg, uint32_t addr, const void *data, long count);
int bdmflash_erase_x16(const flash_alg_info_t *alg, uint32_t addr, long size);
int bdmflash_check_id_x8(const flash_alg_info_t *alg, uint32_t addr, flash_d_t retid[2]);
int bdmflash_prog_x8(const flash_alg_info_t *alg, uint32_t addr, const void *data, long count);
int bdmflash_erase_x8(const flash_alg_info_t *alg, uint32_t addr, long size);
/* predefined flash types */
flash_alg_info_t amd_29f800_x16={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0xfffff, /* 1MB */
reg1_addr: 0x555*2,
reg2_addr: 0x2aa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x16,
cmd_unlock1:0xaa, /* reg1 */
cmd_unlock2:0x55, /* reg2 */
cmd_rdid: 0x90, /* reg1 */
cmd_prog: 0xa0, /* reg1 */
cmd_erase: 0x80, /* reg1 */
cmd_reset: 0xf0, /* any */
erase_all: 0x10, /* reg1 */
erase_sec: 0x30, /* sector */
fault_bit: 0x20,
manid: 1,
devid: 0x2258,
alg_name: "amd29f800"
};
flash_alg_info_t amd_29f400_x16={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0x7ffff, /* 0.5MB */
reg1_addr: 0x555*2,
reg2_addr: 0x2aa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x16,
cmd_unlock1:0xaa, /* reg1 */
cmd_unlock2:0x55, /* reg2 */
cmd_rdid: 0x90, /* reg1 */
cmd_prog: 0xa0, /* reg1 */
cmd_erase: 0x80, /* reg1 */
cmd_reset: 0xf0, /* any */
erase_all: 0x10, /* reg1 */
erase_sec: 0x30, /* sector */
fault_bit: 0x20,
manid: 1,
devid: 0x22ab,
alg_name: "amd29f400"
};
flash_alg_info_t amd_29f040_x8={
check_id: bdmflash_check_id_x8,
prog: bdmflash_prog_x8,
erase: bdmflash_erase_x8,
addr_mask: 0x7ffff, /* 0.5MB */
reg1_addr: 0x555,
reg2_addr: 0x2aa,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8,
cmd_unlock1:0xaa, /* reg1 */
cmd_unlock2:0x55, /* reg2 */
cmd_rdid: 0x90, /* reg1 */
cmd_prog: 0xa0, /* reg1 */
cmd_erase: 0x80, /* reg1 */
cmd_reset: 0xf0, /* any */
erase_all: 0x10, /* reg1 */
erase_sec: 0x30, /* sector */
fault_bit: 0x20,
manid: 1,
devid: 0xa4,
alg_name: "amd29f040"
};
flash_alg_info_t amd_29f010_x8x2={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0x3ffff, /* 2x128kB = 256kB */
reg1_addr: 0x5555*2,
reg2_addr: 0x2aaa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8x2,
cmd_unlock1:0xaaaa, /* reg1 */
cmd_unlock2:0x5555, /* reg2 */
cmd_rdid: 0x9090, /* reg1 */
cmd_prog: 0xa0a0, /* reg1 */
cmd_erase: 0x8080, /* reg1 */
cmd_reset: 0xf0f0, /* any */
erase_all: 0x1010, /* reg1 */
erase_sec: 0x3030, /* sector */
fault_bit: 0x2020,
manid: 0x0101,
devid: 0x2020,
alg_name: "amd29f010x2"
};
flash_alg_info_t at_49f040_x8x2={
check_id: bdmflash_check_id_x16,
prog: bdmflash_prog_x16,
erase: bdmflash_erase_x16,
addr_mask: 0xfffff, /* 2x0.5MB = 1MB */
reg1_addr: 0x5555*2,
reg2_addr: 0x2aaa*2,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8x2,
cmd_unlock1:0xaaaa, /* reg1 */
cmd_unlock2:0x5555, /* reg2 */
cmd_rdid: 0x9090, /* reg1 */
cmd_prog: 0xa0a0, /* reg1 */
cmd_erase: 0x8080, /* reg1 */
cmd_reset: 0xf0f0, /* any */
erase_all: 0x1010, /* reg1 */
erase_sec: 0x3030, /* sector */
fault_bit: 0x2020,
manid: 0x1F1F,
devid: 0x1313,
alg_name: "at49f040x2"
};
#ifdef WITH_TARGET_BUS32
flash_alg_info_t amd_29f080_x8x4={
check_id: bdmflash_check_id_x32,
prog: bdmflash_prog_x32,
erase: bdmflash_erase_x32,
addr_mask: 0x3fffff, /* 4x1MB */
reg1_addr: 0x555*4,
reg2_addr: 0x2aa*4,
sec_size: 0x10000,
width: FLASH_ALG_BITS_x8x4,
cmd_unlock1:0xaaaaaaaa, /* reg1 */
cmd_unlock2:0x55555555, /* reg2 */
cmd_rdid: 0x90909090, /* reg1 */
cmd_prog: 0xa0a0a0a0, /* reg1 */
cmd_erase: 0x80808080, /* reg1 */
cmd_reset: 0xf0f0f0f0, /* any */
erase_all: 0x10101010, /* reg1 */
erase_sec: 0x30303030, /* sector */
fault_bit: 0x20202020,
manid: 0x01010101,
devid: 0xd5d5d5d5,
alg_name: "amd29f080x4"
};
#endif /* WITH_TARGET_BUS32 */
/* please keep sorted by flash sizes, smallest first */
flash_alg_info_t *flash_alg_infos_def[]={
&amd_29f010_x8x2, /* 256 kB */
&amd_29f040_x8, /* 512 kB */
&amd_29f400_x16, /* 512 kB */
&amd_29f800_x16, /* 1 MB */
&at_49f040_x8x2, /* 1 MB */
#ifdef WITH_TARGET_BUS32
&amd_29f080_x8x4, /* 4 MB */
#endif /* WITH_TARGET_BUS32 */
NULL
};
flash_alg_info_t **flash_alg_infos=flash_alg_infos_def;
#if 0
#define FLASH_WR32(adr,val) (*(volatile uint32_t*)(adr)=(val))
#define FLASH_RD32(adr) (*(volatile uint32_t*)(adr))
#define FLASH_WR16(adr,val) (*(volatile uint16_t*)(adr)=(val))
#define FLASH_RD16(adr) (*(volatile uint16_t*)(adr))
#define FLASH_WR8(adr,val) (*(volatile unsigned int8_t*)(adr)=(val))
#define FLASH_RD8(adr) (*(volatile unsigned int8_t*)(adr))
#elif 0
#define FLASH_WR32(adr,val) \
({ \
if(bdmlib_write_var(adr,BDM_SIZE_LONG,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD32(adr) \
({ uint32_t temp_val; \
if(bdmlib_read_var(adr,BDM_SIZE_LONG,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#define FLASH_WR16(adr,val) \
({ \
if(bdmlib_write_var(adr,BDM_SIZE_WORD,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD16(adr) \
({ uint16_t temp_val; \
if(bdmlib_read_var(adr,BDM_SIZE_WORD,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#define FLASH_WR8(adr,val) \
({ \
if(bdmlib_write_var(adr,BDM_SIZE_BYTE,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD8(adr) \
({ unsigned int8_t temp_val; \
if(bdmlib_read_var(adr,BDM_SIZE_BYTE,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#else
#define FLASH_WR32(adr,val) \
({ \
if(bdmWriteLongWord((unsigned long)adr,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD32(adr) \
({ unsigned long temp_val; \
if(bdmReadLongWord((unsigned long)adr,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#define FLASH_WR16(adr,val) \
({ \
if(bdmWriteWord((unsigned long)adr,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD16(adr) \
({ unsigned short temp_val; \
if(bdmReadWord((unsigned long)adr,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#define FLASH_WR8(adr,val) \
({ \
if(bdmWriteByte((unsigned long)adr,val)<0) \
goto mem_op_error; \
val; \
})
#define FLASH_RD8(adr) \
({ unsigned char temp_val; \
if(bdmReadByte((unsigned long)adr,&temp_val)<0) \
goto mem_op_error; \
temp_val; \
})
#endif
static
int bdmflash_prepval_x16(uint16_t *pval, uint32_t addr, const void *data, long count)
{
if(!((long)addr&1) && (count>=2)){
*pval=(((unsigned char*)data)[0]<<8)|(((unsigned char*)data)[1]);
return 2;
}
if(!count) return count;
if(!((long)addr&1)){
*pval=(((unsigned char*)data)[0]<<8) | FLASH_RD8(addr+1);
}else{
*pval=(FLASH_RD8(addr-1)<<8) | (((unsigned char*)data)[0]);
}
return 1;
mem_op_error:
return -4;
}
#ifdef WITH_TARGET_BUS32
static
int bdmflash_prepval_x32(uint32_t *pval, uint32_t addr, const void *data, long count)
{
int offs=(long)addr&3;
int rest=4-offs;
uint32_t val=0;
if(!offs && (count>=4)){
*pval=((uint32_t)((unsigned char*)data)[0]<<24)|((uint32_t)((unsigned char*)data)[1]<<16)|
(((unsigned char*)data)[2]<<8)|(((unsigned char*)data)[3]);
return 4;
}
if(!count) return count;
if(count>rest) count=rest;
while(offs){
val<<=8;
val|=FLASH_RD8(addr-offs);
offs--;
}
while(offs<count){
val<<=8;
val|=((unsigned char*)data)[offs];
offs++;
}
while(offs<rest){
val<<=8;
val|=FLASH_RD8(addr+offs);
offs++;
}
*pval=val;
return count;
mem_op_error:
return -4;
}
#endif /* WITH_TARGET_BUS32 */
/*******************************************************************/
/* routines for 16 bit wide Intel or AMD flash or two interleaved
8 bit flashes */
int bdmflash_check_id_x16(const flash_alg_info_t *alg, uint32_t addr, flash_d_t retid[2])
{
int ret=0;
uint16_t devid, manid;
uint32_t a=addr&~alg->addr_mask;
/* reset */
FLASH_WR16(a,alg->cmd_reset);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* read manufacturer ID */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_rdid);
manid=FLASH_RD16(a+0);
if(manid!=alg->manid) ret=-1;
/* reset */
FLASH_WR16(a,alg->cmd_reset);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* read device ID */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_rdid);
devid=FLASH_RD16(a+2);
if(devid!=alg->devid) ret=-1;
/* reset */
FLASH_WR16(a,alg->cmd_reset);
if(retid)
{retid[0]=manid;retid[1]=devid;};
return ret;
mem_op_error:
return -5;
}
int bdmflash_prog_x16(const flash_alg_info_t *alg, uint32_t addr,
const void *data, long count)
{
int ret;
uint16_t old,new,fault,val;
uint32_t a=addr&~alg->addr_mask;
ret=bdmflash_prepval_x16(&val,addr,data,count);
if(ret<=0)
return ret;
addr=addr&~1l;
/* check if FLASH needs programming */
if(1){
old=FLASH_RD16(addr);
if(old==val) return ret;
}
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* program command */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_prog);
FLASH_WR16(addr,val);
/* wait for result */
old=FLASH_RD16(addr);
while((new=FLASH_RD16(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x8x2 */
if(!(old^=(new=FLASH_RD16(addr)))) break; /* finished now */
else{
/* one chip of x8x2 configuration can finish earlier */
if(!(old&0x00ff)||(fault&0x00ff))
if(!(old&0xff00)||(fault&0xff00))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR16(a,alg->cmd_reset);
if((FLASH_RD16(addr)!=val) && (ret>=0)) ret=-3;
return ret;
mem_op_error:
return -5;
}
int bdmflash_erase_x16(const flash_alg_info_t *alg, uint32_t addr, long size)
{
uint16_t old,new,fault;
int ret=0;
uint32_t a=addr&~alg->addr_mask;
/* reset */
FLASH_WR16(a,alg->cmd_reset);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* erase command */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_erase);
/* security sequence */
FLASH_WR16(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR16(a+alg->reg2_addr,alg->cmd_unlock2);
/* select erase range */
a=addr;
if(size==0)
FLASH_WR16(a+alg->reg1_addr,alg->erase_all);
else{
FLASH_WR16(addr,alg->erase_sec);
}
/* wait for result */
old=FLASH_RD16(addr);
while((new=FLASH_RD16(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x8x2 */
if(!(old^=(new=FLASH_RD16(addr)))) break; /* finished now */
else{
/* one chip of x8x2 configuration can finish earlier */
if(!(old&0x00ff)||(fault&0x00ff))
if(!(old&0xff00)||(fault&0xff00))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR16(a,alg->cmd_reset);
if(FLASH_RD16(addr)!=0xffff) ret--;
return ret;
mem_op_error:
return -5;
}
/*******************************************************************/
/* routines for single 8 bit wide Intel or AMD flash */
int bdmflash_check_id_x8(const flash_alg_info_t *alg, uint32_t addr,
flash_d_t retid[2])
{
int ret=0;
uint16_t devid, manid;
uint32_t a=addr&~alg->addr_mask;
/* reset */
FLASH_WR8(a,alg->cmd_reset);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* read manufacturer ID */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_rdid);
manid=FLASH_RD8(a+0);
if(manid!=alg->manid) ret=-1;
/* reset */
FLASH_WR8(a,alg->cmd_reset);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* read device ID */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_rdid);
devid=FLASH_RD8(a+1);
if(devid!=alg->devid) ret=-1;
/* reset */
FLASH_WR8(a,alg->cmd_reset);
if(retid)
{retid[0]=manid;retid[1]=devid;};
return ret;
mem_op_error:
return -5;
}
int bdmflash_prog_x8(const flash_alg_info_t *alg, uint32_t addr, const void *data, long count)
{
int ret=1;
unsigned char old,new,val;
uint32_t a=addr&~alg->addr_mask;
val=*(unsigned char*)data;
/* check if FLASH needs programming */
if(1){
old=FLASH_RD8(addr);
if(old==val) return ret;
}
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* program command */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_prog);
FLASH_WR8(addr,val);
/* wait for result */
old=FLASH_RD8(addr);
while((new=FLASH_RD8(addr))!=old){
if((old&alg->fault_bit)&&(new&alg->fault_bit)){
if((FLASH_RD8(addr))!=new) ret=-2;
break;
}
old=new;
}
/* reset */
FLASH_WR8(a,alg->cmd_reset);
if((FLASH_RD8(addr)!=val) && (ret>=0)) ret=-3;
return ret;
mem_op_error:
return -5;
}
int bdmflash_erase_x8(const flash_alg_info_t *alg, uint32_t addr, long size)
{
unsigned char old,new;
int ret=0;
uint32_t a=addr&~alg->addr_mask;
/* reset */
FLASH_WR8(a,alg->cmd_reset);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* erase command */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_erase);
/* security sequence */
FLASH_WR8(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR8(a+alg->reg2_addr,alg->cmd_unlock2);
/* select erase range */
a=addr;
if(size==0)
FLASH_WR8(a+alg->reg1_addr,alg->erase_all);
else{
FLASH_WR8(addr,alg->erase_sec);
}
old=FLASH_RD8(addr);
while((new=FLASH_RD8(addr))!=old){
if((old&alg->fault_bit)&&(new&alg->fault_bit)){
if((FLASH_RD8(addr))!=new) ret=-2;
break;
}
old=new;
}
/* reset */
FLASH_WR8(a,alg->cmd_reset);
if(FLASH_RD16(addr)!=0xffff) ret--;
return ret;
mem_op_error:
return -5;
}
/*******************************************************************/
/* routines for two/four interleaved 16/8 bit wide Intel or AMD flashes */
#ifdef WITH_TARGET_BUS32
int bdmflash_check_id_x32(const flash_alg_info_t *alg, uint32_t addr, flash_d_t retid[2])
{
int ret=0;
uint32_t devid, manid;
uint32_t a=addr&~alg->addr_mask;
/* reset */
FLASH_WR32(a,alg->cmd_reset);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* read manufacturer ID */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_rdid);
/* bank slecets swapped as i suspect (360DK only) !!!!!! */
/*manid=FLASH_RD32(a+0xc); */
manid=FLASH_RD32(a+0);
if(manid!=alg->manid) ret=-1;
/* reset */
FLASH_WR32(a,alg->cmd_reset);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* read device ID */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_rdid);
devid=FLASH_RD32(a+4);
if(devid!=alg->devid) ret=-1;
/* reset */
FLASH_WR32(a,alg->cmd_reset);
if(retid)
{retid[0]=manid;retid[1]=devid;};
return ret;
mem_op_error:
return -5;
}
int bdmflash_prog_x32(const flash_alg_info_t *alg, uint32_t addr,
const void *data, long count)
{
int ret=4;
uint32_t old,new,fault,val;
uint32_t a=addr&~alg->addr_mask;
ret=bdmflash_prepval_x32(&val,addr,data,count);
if(ret<=0)
return ret;
addr=addr&~3l;
/* check if FLASH needs programming */
if(1){
old=FLASH_RD32(addr);
if(old==val) return ret;
}
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* program command */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_prog);
FLASH_WR32(addr,val);
/* wait for result */
old=FLASH_RD32(addr);
while((new=FLASH_RD32(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x8x2 */
if(!(old^=(new=FLASH_RD32(addr)))) break; /* finished now */
else{
/* one chip of x16x2 or x8x4 configuration can finish earlier */
if(!(old&0x000000ff)||(fault&0x000000ff))
if(!(old&0x0000ff00)||(fault&0x0000ff00))
if(!(old&0x00ff0000)||(fault&0x00ff0000))
if(!(old&0xff000000)||(fault&0xff000000))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR32(a,alg->cmd_reset);
if((FLASH_RD32(addr)!=val) && (ret>=0)) ret=-3;
return ret;
mem_op_error:
return -5;
}
int bdmflash_erase_x32(const flash_alg_info_t *alg, uint32_t addr, long size)
{
uint32_t old,new,fault;
int ret=0;
uint32_t a=addr&~alg->addr_mask;
/* reset */
FLASH_WR32(a,alg->cmd_reset);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* erase command */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_erase);
/* security sequence */
FLASH_WR32(a+alg->reg1_addr,alg->cmd_unlock1);
if(alg->cmd_unlock2)
FLASH_WR32(a+alg->reg2_addr,alg->cmd_unlock2);
/* select erase range */
a=addr;
if(size==0)
FLASH_WR32(a+alg->reg1_addr,alg->erase_all);
else{
FLASH_WR32(addr,alg->erase_sec);
}
/* wait for result */
old=FLASH_RD32(addr);
while((new=FLASH_RD32(addr))!=old){
if((fault=old&new&alg->fault_bit)){
old=new;
/* check for some false fault at finish or race of x16x2 or x8x4 */
if(!(old^=(new=FLASH_RD32(addr)))) break; /* finished now */
else{
/* one chip of x16x2 or x8x4 configuration can finish earlier */
if(!(old&0x000000ff)||(fault&0x000000ff))
if(!(old&0x0000ff00)||(fault&0x0000ff00))
if(!(old&0x00ff0000)||(fault&0x00ff0000))
if(!(old&0xff000000)||(fault&0xff000000))
{ret=-2;break;}
}
}
old=new;
}
/* reset */
FLASH_WR32(a,alg->cmd_reset);
if(FLASH_RD32(addr)!=0xffffffff) ret--;
return ret;
mem_op_error:
return -5;
}
#endif /* WITH_TARGET_BUS32 */
/*******************************************************************/
/* flash type independent check_id */
int bdmflash_check_id(const flash_alg_info_t *alg, uint32_t addr, flash_d_t retid[2])
{
if(alg->check_id)
return alg->check_id(alg, addr, retid);
else
return -10; /* we really need to define error constants in future */
}
/* flash type independent program one location */
int bdmflash_prog(const flash_alg_info_t *alg, uint32_t addr, const void *data, long count)
{
if(alg->prog)
return alg->prog(alg,addr,data,count);
else
return -10;
}
/* flash type independent erase region */
int bdmflash_erase(const flash_alg_info_t *alg, uint32_t addr, long size)
{
if(alg->erase)
return alg->erase(alg,addr,size);
else
return -10;
}
const flash_alg_info_t *
bdmflash_alg_from_id(flash_d_t id[2])
{
int i;
const flash_alg_info_t *alg;
for(i=0;(alg=flash_alg_infos_def[i])!=NULL;i++)
if((alg->manid==id[0])&&(alg->devid==id[0]))
return alg;
return NULL;
}
const flash_alg_info_t *
bdmflash_alg_probe(uint32_t flash_adr)
{
int i;
const flash_alg_info_t *alg,*alg1;
flash_d_t testid[2];
for(i=0;(alg=flash_alg_infos_def[i])!=NULL;i++){
if(bdmflash_check_id(alg,flash_adr,testid)>=0)
return alg;
alg1=bdmflash_alg_from_id(testid);
if(alg1!=NULL)
if(bdmflash_check_id(alg1,flash_adr,testid)>=0)
return alg1;
}
return NULL;
}
int
bdmflash_wrb_filt(bdmlib_bfilt_t * filt, uint32_t in_adr,
unsigned int size, unsigned char * bl_ptr)
{
int offs=0,res;
flash_d_t val;
const flash_alg_info_t *alg=(flash_alg_info_t*)filt->info;
#if 0
if(alg->width!=FLASH_ALG_BITS_x8) {
/* 16 bit wide flash write path */
if((u_long)in_adr&1) {
in_adr-=1;
val=(FLASH_RD16(in_adr)&0xff00)|bl_ptr[offs];
if((res=bdmflash_prog(alg, in_adr, val))<0) {
fprintf(stderr, "flash byte write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
in_adr+=2;
size-=1;
offs+=1;
}
while(size>=2) {
val=(bl_ptr[offs]<<8)|bl_ptr[offs+1];
if((res=bdmflash_prog(alg, in_adr, val))<0) {
fprintf(stderr, "flash write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
in_adr+=2;
size-=2;
offs+=2;
}
if(size) {
val=(FLASH_RD16(in_adr)&0x00ff)|(bl_ptr[offs]<<8);
if((res=bdmflash_prog(alg, in_adr, val))<0) {
fprintf(stderr, "flash byte write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
size-=1;
offs+=1;
}
}
#endif
while(size>=1) {
val=bl_ptr[offs];
if((res=bdmflash_prog(alg, in_adr, bl_ptr+offs, size))<=0) {
fprintf(stderr, "flash write error %d at 0x%lx\n",
res,(u_long)in_adr);
return offs;
}
in_adr+=res;
size-=res;
offs+=res;
}
return offs;
#if 0
mem_op_error:
fprintf(stderr, "bdm memory access error\n");
return 0;
#endif
}
int
bdmflash_erase_filt(bdmlib_bfilt_t * filt, uint32_t in_adr, unsigned int size)
{
int res=0;
const flash_alg_info_t *alg=(flash_alg_info_t*)filt->info;
if(!in_adr)
in_adr=filt->begin_adr;
res=bdmflash_erase(alg, in_adr,size);
if(res<0)
fprintf(stderr, "flash erase error %d\n",res);
return res;
}
#if 0
/* slow version of blank check */
int
bdmflash_blankck_filt(bdmlib_bfilt_t * filt, uint32_t in_adr, unsigned int size)
{
int errors=0;
if(!in_adr||!size){
in_adr=filt->begin_adr;
size=filt->end_adr-in_adr+1;
}
if(((long)in_adr&1)&&size){
if(FLASH_RD8(in_adr)!=0xff){
fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
errors++;
}
in_adr++; size--;
}
while(size>=2){
if(FLASH_RD16(in_adr)!=0xffff){
if(errors<5){
if(errors) fprintf(stderr,",0x%06lX",(long)in_adr);
else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
}else if(errors==5) fprintf(stderr, " and more");
errors++;
}
if(!((long)in_adr&0xfff)) bdmlib_propeller(stdout);
in_adr+=2; size-=2;
}
if(size){
if(FLASH_RD8(in_adr)!=0xff){
if(errors) fprintf(stderr,",0x%06lX",(long)in_adr);
else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
errors++;
}
}
if(errors) fprintf(stderr,"\n");
return errors;
mem_op_error:
fprintf(stderr, "bdm memory access error\n");
return -5;
}
#else
/* hopefully faster version of blank check */
int
bdmflash_blankck_filt(bdmlib_bfilt_t * filt, uint32_t in_adr,
unsigned int size)
{
int errors=0, in_buf;
unsigned char buf[1024], *p;
if(!in_adr||!size){
in_adr=filt->begin_adr;
size=filt->end_adr-in_adr+1;
}
while(size){
if(size<sizeof(buf)) in_buf=size;
else in_buf=sizeof(buf);
if(bdmlib_read_block(in_adr,in_buf,buf)!=in_buf)
goto mem_op_error;
size-=in_buf;
for(p=buf;in_buf--;in_adr++,p++){
if(*p!=0xff){
if(errors<10){
if(errors) fprintf(stderr,",0x%06lX",(long)in_adr);
else fprintf(stderr,"blank check error at 0x%06lX",(long)in_adr);
}else if(errors==10) fprintf(stderr, " and more");
errors++;
}
}
bdmlib_propeller((u_long)in_adr, stdout);
}
if(errors) fprintf(stderr,"\n");
return errors;
mem_op_error:
fprintf(stderr, "\nbdm memory access error\n");
return -5;
}
#endif

75
m68k/flashlib/bdmflash.h Normal file
View File

@@ -0,0 +1,75 @@
#ifndef BDMFLASH_H
#define BDMFLASH_H
#include <sys/types.h>
#include <stdint.h>
#define FLASH_ALG_BITS_x8 0
#define FLASH_ALG_BITS_x16 2
#define FLASH_ALG_BITS_x8x2 3
#define FLASH_ALG_BITS_x32 4
#define FLASH_ALG_BITS_x16x2 5
#define FLASH_ALG_BITS_x8x4 7
#define WITH_TARGET_BUS32
#ifndef WITH_TARGET_BUS32
typedef uint16_t flash_d_t; /* Type able to store one flash location */
#else /* WITH_TARGET_BUS32 */
typedef uint32_t flash_d_t; /* Type able to store one flash location */
#endif /* WITH_TARGET_BUS32 */
/* Structure describing programming operations for flash type */
typedef struct flash_alg_info {
/* Sets retid to manufacturer and type ID, returns <0 in case of error */
int (*check_id)(const struct flash_alg_info *alg, uint32_t addr, flash_d_t retid[2]);
/* Programs one location of flash and returns number of programmed bytes */
int (*prog)(const struct flash_alg_info *alg, uint32_t addr, const void *data, long count);
/* Erase all sectors overlaped by region from addr of size bytes, size=0 => erase all */
/* This version is capable only of full erase (size=0) and one sector (size=1) */
int (*erase)(const struct flash_alg_info *alg, uint32_t addr, long size);
/* Numeric and string fields follows */
uint32_t addr_mask; /* Mask to take offset inside flash */
uint32_t reg1_addr; /* Flash control register 1 */
uint32_t reg2_addr; /* Flash control register 2 */
uint32_t sec_size; /* block size of bigger blocks */
flash_d_t width; /* FLASH_ALG_BITS_x8 .. 8 bit data bus,
FLASH_ALG_BITS_x16 .. 16 bit data,
FLASH_ALG_BITS_x8x2 .. two interleaved 8 bit */
flash_d_t cmd_unlock1;/* first byte of command sequence */
flash_d_t cmd_unlock2;/* second byte of command sequence */
flash_d_t cmd_rdid; /* read identifier */
flash_d_t cmd_prog; /* program one loc */
flash_d_t cmd_erase; /* erase command */
flash_d_t cmd_reset; /* leave program mode */
flash_d_t erase_all; /* erase all */
flash_d_t erase_sec; /* erase sector */
flash_d_t fault_bit; /* programing of location failed */
flash_d_t manid; /* manufacturer ID */
flash_d_t devid; /* device ID */
char *alg_name; /* informative flash type name */
} flash_alg_info_t;
int bdmflash_check_id(const flash_alg_info_t *alg, uint32_t addr,
flash_d_t retid[2]);
int bdmflash_prog(const flash_alg_info_t *alg, uint32_t addr, const void *data, long count);
int bdmflash_erase(const flash_alg_info_t *alg, uint32_t addr, long size);
flash_alg_info_t **flash_alg_infos;
const flash_alg_info_t *bdmflash_alg_from_id(flash_d_t id[2]);
const flash_alg_info_t *bdmflash_alg_probe(uint32_t flash_adr);
int bdmflash_wrb_filt(bdmlib_bfilt_t * filt, uint32_t in_adr,
unsigned int size, u_char * bl_ptr);
int bdmflash_erase_filt(bdmlib_bfilt_t * filt, uint32_t in_adr, unsigned int size);
int bdmflash_blankck_filt(bdmlib_bfilt_t * filt, uint32_t in_adr, unsigned int size);
int bdmflash_check_id(const flash_alg_info_t *alg, uint32_t addr, flash_d_t retid[2]);
#endif /* BDMFLASH_H */

448
m68k/flashlib/elf-utils.c Executable file
View File

@@ -0,0 +1,448 @@
/*
* $Id: elf-utils.c,v 1.2 2008/07/31 01:53:44 cjohns Exp $
*
* Motorola Background Debug Mode Driver
* Copyright (C) 2008 Chris Johns
*
* 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
*
* ELF Support for libelf.
*/
#include <fcntl.h>
#include <string.h>
#include <stdint.h>
#include <elf-utils.h>
#if defined (__WIN32__)
#define ELF_OPEN_MODE (O_RDONLY | O_BINARY)
#else
#define ELF_OPEN_MODE (O_RDONLY)
#endif
void
elf_handle_init (elf_handle* handle)
{
memset (handle, 0, sizeof (*handle));
}
int
elf_open (const char* file, elf_handle* handle, elf_output output)
{
if (handle->fd)
{
if (output)
output ("elf-utils: ELF handle already initialised\n");
return 0;
}
if (elf_version (EV_CURRENT) == EV_NONE)
{
if (output)
output ("elf-utils: ELF library initialization failed: %s\n",
elf_errmsg (-1));
return 0;
}
handle->output = output;
if ((handle->fd = open (file, ELF_OPEN_MODE, 0)) < 0)
{
if (handle->output)
output ("elf-utils: open %s failed\n", file);
return 0;
}
if ((handle->elf = elf_begin (handle->fd, ELF_C_READ, NULL)) == NULL)
{
close (handle->fd);
handle->fd = 0;
if (handle->output)
output ("elf-utils: elf_begin failed: %s\n", elf_errmsg (-1));
return 0;
}
handle->file = strdup (file);
handle->ek = elf_kind (handle->elf);
/*
* Check the executable header.
*/
if (gelf_getehdr (handle->elf, &handle->ehdr) == NULL)
{
if (handle->output)
output ("elf-utils: elf_getehdr failed: %s\n", elf_errmsg (-1));
elf_close (handle);
return 0;
}
if (handle->ehdr.e_machine != EM_68K)
{
if (handle->output)
output ("elf-utils: machine type not Motorola 68000\n");
elf_close (handle);
return 0;
}
if ((handle->ehdr.e_type != ET_REL) && (handle->ehdr.e_type != ET_EXEC))
{
output ("elf-utils: file type no relocable or executable\n");
elf_close (handle);
return 0;
}
if ((handle->eclass = gelf_getclass (handle->elf)) == ELFCLASSNONE)
{
if (handle->output)
output ("elf-utils: elf_getclass failed: %s\n", elf_errmsg (-1));
elf_close (handle);
return 0;
}
/*
* No 64-bit Coldfires yet !
*/
if (handle->eclass != ELFCLASS32)
{
if (handle->output)
output ("elf-utils: ELF 64-bit, only 32-bit support: %s\n",
handle->file);
elf_close (handle);
return 0;
}
if (elf_getshnum (handle->elf, &handle->shnum) == 0)
{
if (handle->output)
output ("elf-utils: elf_getshnum failed: %s\n", elf_errmsg (-1));
elf_close (handle);
return 0;
}
if (elf_getshstrndx (handle->elf, &handle->shstrndx) == 0)
{
if (handle->output)
output ("elf-utils: elf_getshstrndx failed: %s\n", elf_errmsg (-1));
elf_close (handle);
return 0;
}
if (elf_getphnum (handle->elf, &handle->phnum) == 0)
{
if (handle->output)
output ("elf-utils: elf_getphnum failed: %s\n", elf_errmsg (-1));
elf_close (handle);
return 0;
}
return 1;
}
int
elf_close (elf_handle* handle)
{
if (!handle->fd)
return 0;
elf_end (handle->elf);
close (handle->fd);
free (handle->file);
handle->elf = NULL;
handle->file = NULL;
handle->fd = 0;
return 1;
}
int
elf_has_symbol_table (elf_handle* handle)
{
Elf_Scn* section = NULL;
while ((section = elf_nextscn (handle->elf, section)) != 0)
{
GElf_Shdr shdr;
if (gelf_getshdr (section, &shdr) != &shdr)
{
if (shdr.sh_type == SHT_SYMTAB)
{
Elf_Data* data = NULL;
data = elf_getdata (section, data);
if ((data == NULL) || (data->d_size == 0))
return 0;
return 1;
}
}
}
return 0;
}
int
elf_get_symbol (elf_handle* handle, const char* label, GElf_Sym* sym)
{
Elf_Scn* section = NULL;
while ((section = elf_nextscn (handle->elf, section)) != 0)
{
GElf_Shdr shdr;
if (gelf_getshdr (section, &shdr) == &shdr)
{
if (shdr.sh_type == SHT_SYMTAB)
{
Elf_Data* data = NULL;
int symbol = 0;
char* name;
data = elf_getdata (section, data);
if ((data == NULL) || (data->d_size == 0))
return 0;
while (gelf_getsym (data, symbol, sym) == sym)
{
name = elf_strptr (handle->elf,
shdr.sh_link, (size_t) sym->st_name);
if (!name)
{
if (handle->output)
handle->output ("elf-utils: find symbol: %s\n",
elf_errmsg (elf_errno ()));
return 0;
}
if (strcmp (label, name) == 0)
return 1;
symbol++;
}
}
}
}
return 0;
}
int
elf_get_section_hdr (elf_handle* handle, int secindex, GElf_Shdr* shdr)
{
Elf_Scn* section = NULL;
int count = 1;
while ((section = elf_nextscn (handle->elf, section)) != 0)
{
if (count == secindex)
{
if (gelf_getshdr (section, shdr) == shdr)
{
return 1;
}
}
count++;
}
return 0;
}
void*
elf_get_section_data (elf_handle* handle, int secindex, uint32_t* size)
{
Elf_Scn* section = NULL;
int count = 1;
*size = 0;
while ((section = elf_nextscn (handle->elf, section)) != 0)
{
if (count == secindex)
{
Elf_Data* data = NULL;
void* buffer;
data = elf_getdata (section, data);
if (data == NULL)
return NULL;
*size = (uint32_t) data->d_size;
return data->d_buf;
}
count++;
}
return 0;
}
void*
elf_get_section_data_sym (elf_handle* handle, const char* label)
{
GElf_Sym esym;
if (elf_get_symbol (handle, label, &esym))
{
Elf_Scn* section = NULL;
int count = 1;
while ((section = elf_nextscn (handle->elf, section)) != 0)
{
if (count == esym.st_shndx)
{
Elf_Data* data = NULL;
data = elf_getdata (section, data);
if ((data == NULL) || (data->d_size == 0))
return NULL;
return ((uint8_t *) data->d_buf) + esym.st_value;
}
count++;
}
}
return NULL;
}
int
elf_map_over_sections (elf_handle* handle, elf_section_handler handler,
const char* sname)
{
/*
* We need to iterate over the sections, and then for each section we decide
* to load, we need to find the program header for that section. we match
* the program header by finding the program header that has the same virtaul
* address range. This yields us with the physical address which is needed
* to know where to load the section on the target. I don't know if this is
* the correct way to do this, if not, please fix.
*/
Elf_Scn* section = NULL;
int count = 1;
size_t num_headers = 0;
if (elf_getphnum (handle->elf, &num_headers) == 0)
{
if (handle->output)
handle->output ("elf-utils: elf_getphnum error\n");
return 0;
}
while ((section = elf_nextscn (handle->elf, section)) != 0)
{
GElf_Shdr shdr;
if (gelf_getshdr (section, &shdr) == &shdr) {
const char* name;
name = elf_strptr (handle->elf, handle->shstrndx, shdr.sh_name);
if (!sname || (strcmp (sname, name) == 0))
{
/*
* Find a LOAD program header in the same virtual address range.
*/
GElf_Addr vaddr = shdr.sh_addr - shdr.sh_offset;
GElf_Phdr phdr;
size_t i;
for (i = 0; i < num_headers; ++i)
{
if (gelf_getphdr (handle->elf, i, &phdr) != &phdr)
{
if (handle->output)
handle->output ("elf-utils: gelf_getphdr error\n");
return 0;
}
if(phdr.p_type == PT_LOAD)
{
if(phdr.p_vaddr <= shdr.sh_addr &&
phdr.p_vaddr + phdr.p_memsz > shdr.sh_addr)
break;
}
}
if(!handler (handle, (i == num_headers) ? 0 : &phdr, &shdr, name, count))
return 0;
}
}
++count;
}
return 1;
}
#define PRINT_FORMAT " %-12s %d\n"
#define PRINT_FORMAT_X " %-12s 0x%x\n"
void
elf_show_exeheader (elf_handle* handle)
{
#define EHDR_PRINT_FIELD(N) do { \
handle->output (PRINT_FORMAT ,#N, (uintmax_t) handle->ehdr.N); \
} while (0)
char* s;
if (!handle->output)
return;
switch (handle->ek)
{
case ELF_K_AR:
s = "ar(1) archive";
break;
case ELF_K_ELF:
s = "elf object";
break;
case ELF_K_NONE:
s = "data";
break;
default:
s = "unrecognized";
}
handle->output ("%s: %s\n", handle->file, s);
EHDR_PRINT_FIELD (e_type);
EHDR_PRINT_FIELD (e_machine);
EHDR_PRINT_FIELD (e_version);
EHDR_PRINT_FIELD (e_entry);
EHDR_PRINT_FIELD (e_phoff);
EHDR_PRINT_FIELD (e_shoff);
EHDR_PRINT_FIELD (e_flags);
EHDR_PRINT_FIELD (e_ehsize);
EHDR_PRINT_FIELD (e_phentsize);
EHDR_PRINT_FIELD (e_shentsize);
handle->output (PRINT_FORMAT, "(shnum)", (uintmax_t) handle->shnum);
handle->output (PRINT_FORMAT, "(shstrndx)", (uintmax_t) handle->shstrndx);
handle->output (PRINT_FORMAT, "(phnum)", (uintmax_t) handle->phnum);
}
void
elf_show_symbol (elf_handle* handle, GElf_Sym* esym)
{
#define ESYM_PRINT_FIELD(N) do { \
handle->output (PRINT_FORMAT_X ,#N, (uintmax_t) esym->N); \
} while (0)
if (!handle->output)
return;
ESYM_PRINT_FIELD (st_name);
ESYM_PRINT_FIELD (st_value);
ESYM_PRINT_FIELD (st_size);
ESYM_PRINT_FIELD (st_info);
ESYM_PRINT_FIELD (st_other);
ESYM_PRINT_FIELD (st_shndx);
}

76
m68k/flashlib/elf-utils.h Executable file
View File

@@ -0,0 +1,76 @@
/*
* Motorola Background Debug Mode Driver
* Copyright (C) 2008 Chris Johns
*
* 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
*
* ELF Support for libelf.
*/
#if !defined (_ELF_UTILS_H_)
#define _ELF_UTILS_H_
#define __LIBELF_INTERNAL__ 1
#include <gelf.h>
/*
* Output routine.
*/
typedef int (*elf_output) (const char *format, ...);
/*
* Handle to access the file via libelf.
*/
typedef struct
{
char* file;
int fd;
Elf* elf;
Elf_Kind ek;
GElf_Ehdr ehdr;
int eclass;
size_t shnum;
size_t shstrndx;
size_t phnum;
elf_output output;
} elf_handle;
/*
* Section handler.
*/
typedef int (*elf_section_handler) (elf_handle* handle,
GElf_Phdr* phdr,
GElf_Shdr* shdr,
const char* sname,
int sindex);
void elf_handle_init (elf_handle* handle);
int elf_open (const char* file, elf_handle* handle, elf_output output);
int elf_close (elf_handle* handle);
int elf_get_symbol (elf_handle* handle, const char* label, GElf_Sym* sym);
int elf_get_section_hdr (elf_handle* handle, int secindex, GElf_Shdr* shdr);
void* elf_get_section_data (elf_handle* handle, int secindex,
uint32_t* size);
void* elf_get_section_data_sym (elf_handle* handle, const char* label);
int elf_map_over_sections (elf_handle* handle,
elf_section_handler handler, const char* sname);
void elf_show_exeheader (elf_handle* handle);
void elf_show_symbol (elf_handle* handle, GElf_Sym* esym);
#endif

689
m68k/flashlib/flash29.c Normal file
View File

@@ -0,0 +1,689 @@
/* $Id: flash29.c,v 1.6 2008/07/31 01:53:44 cjohns Exp $
*
* Driver for 29Fxxx and 49Fxxx flash chips.
*
* 2003-12-28 Josef Wolf (jw@raven.inka.de)
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
/* This piece of code arose from ad-hoc code-snippets which I threw into
discussions on the bdm-devel mailing list and in private mails to Pavel
Pisa. I have put those pieces together, removed compiler-errors, rewrote
them several times and optimized somewhat.
This code supports:
- 29Fxxx and 49Fxxx types of flash chips.
- Host-only, target-assisted and target-only operation modes.
- Bus widths of 1, 2 and 4 bytes.
- Chip widths of 1, 2 and 4 bytes.
- Autodetection of known chips on arbitrary bus/chip width combinations.
- Fast bypass unlock programming mode on chips that support it.
- Unaligned programming.
*/
/* Todo:
CSI command set? What is this?
CFI specification http://www.amd.com/products/nvd/overview/cfi.html
*/
#include "flash29.h"
#include "flash_filter.h"
#if HOST_FLASHING
# include <stdio.h>
# include <BDMlib.h>
#endif
/* This defines details for the flash algorithm.
*/
typedef struct
{
uint32_t cmd_unlock1;
uint32_t cmd_unlock2;
uint32_t cmd_reset;
uint32_t cmd_autoselect;
uint32_t cmd_program;
uint32_t cmd_erase;
uint32_t cmd_chiperase;
uint32_t cmd_secterase;
uint32_t cmd_bypass;
uint32_t cmd_resbypass1;
uint32_t cmd_resbypass2;
uint32_t timeout_mask;
uint32_t adr_unlock1;
uint32_t adr_unlock2;
} alg_info_t;
typedef struct
{
const char *name;
const uint32_t manufacturer, device_id;
const uint32_t size; /* in bytes */
const alg_info_t *alg_info;
} chip_t;
typedef struct
{
const alg_info_t *alg_info; /* algorithm information */
uint32_t adr; /* base adress of the chip */
uint32_t size; /* in bytes */
uint32_t chip_width; /* 1->8bit, 2->16bit, 4->32bit */
uint32_t bus_width; /* 1->8bit, 2->16bit, 4->32bit */
uint32_t wait_adr; /* address to check when waiting for erase */
/* From here on, everything is redundant. The only reason to maintain this
redundant information is optimization. */
uint32_t reg1; /* address of unlock register 1 */
uint32_t reg2; /* address of unlock register 2 */
/* This information is placed at the end of the struct because
download_struct() don't need to fiddle around with it. */
void (*wr_func) (uint32_t, uint32_t); /* write function */
uint32_t(*rd_func) (uint32_t); /* read function */
uint32_t bus_mask; /* Mask to get bus_width lowest bytes */
uint32_t chip_mask; /* Mask to get chip_width lowest bytes */
uint32_t shift; /* shift for multiplication by bus_width */
} chiptype_t;
static const alg_info_t alg_29_std = { /* standard 29fxx chips */
0xaaaaaaaa, /* unlock 1 command */
0x55555555, /* unlock 2 command */
0xf0f0f0f0, /* res */
0x90909090, /* asel */
0xa0a0a0a0, /* prog */
0x80808080, /* erase */
0x10101010, /* chiperase */
0x30303030, /* secterase */
0x00000000, /* no unlock bypass */
0x90909090, /* unlock bypass res1 */
0x00000000, /* unlock bypass res2 */
0x20, /* timeout bitmask */
0x555, /* register 1 */
0x2aa, /* register 5 */
};
static const alg_info_t alg_29_unl = { /* 29fxx with unlock bypass mode */
0xaaaaaaaa, /* unlock 1 command */
0x55555555, /* unlock 2 command */
0xf0f0f0f0, /* res */
0x90909090, /* asel */
0xa0a0a0a0, /* prog */
0x80808080, /* erase */
0x10101010, /* chiperase */
0x30303030, /* secterase */
0x20202020, /* unlock bypass */
0x90909090, /* unlock bypass res1 */
0x00000000, /* unlock bypass res2 */
0x20, /* timeout bitmask */
0x555, /* register 1 */
0x2aa, /* register 5 */
};
static const alg_info_t alg_49 = { /* 49fxx and 39fxx chips */
0xaaaaaaaa, /* unlock 1 command */
0x55555555, /* unlock 2 command */
0xf0f0f0f0, /* res */
0x90909090, /* asel */
0xa0a0a0a0, /* prog */
0x80808080, /* erase */
0x10101010, /* chiperase */
0x30303030, /* secterase *//* Block erase ? */
0x00000000, /* no unlock bypass */
0x90909090, /* unlock bypass res1 */
0x00000000, /* unlock bypass res2 */
0x00, /* no timeout support */
0x5555, /* register 1 */
0x2aaa, /* register 5 */
};
/* Here come the known chips.
*/
static const chip_t chips[] = {
{"Am29LV001BT", 0x01, 0xed, 0x20000, &alg_29_unl}, /* AMD */
{"Am29LV001BB", 0x01, 0x6d, 0x20000, &alg_29_unl}, /* AMD */
{"Am29LV002T", 0x01, 0x40, 0x40000, &alg_29_std}, /* AMD */
{"Am29LV002B", 0x01, 0xc2, 0x40000, &alg_29_std}, /* AMD */
{"Am29LV004T", 0x01, 0xb5, 0x80000, &alg_29_std}, /* AMD */
{"Am29LV004B", 0x01, 0xb6, 0x80000, &alg_29_std}, /* AMD */
{"Am29LV008BT", 0x01, 0x3e, 0x100000, &alg_29_unl}, /* AMD */
{"Am29LV008BB", 0x01, 0x37, 0x100000, &alg_29_unl}, /* AMD */
{"Am29LV017B", 0x01, 0xc8, 0x200000, &alg_29_unl}, /* AMD */
{"Am29F010B", 0x01, 0x20, 0x20000, &alg_29_std}, /* AMD */
{"At49F040", 0x1f, 0x13, 0x80000, &alg_49}, /* Atmel */
{"Am29F040B", 0x01, 0xa4, 0x80000, &alg_29_std}, /* AMD */
{"Am29F400BT", 0x01, 0x2223, 0x80000, &alg_29_std}, /* AMD */
{"Am29F400BB", 0x01, 0x22ab, 0x80000, &alg_29_std}, /* AMD */
{"MBM29F400TC", 0x04, 0x2223, 0x80000, &alg_29_std}, /* Fujitsu */
{"MBM29F400BC", 0x04, 0x22ab, 0x80000, &alg_29_std}, /* Fujitsu */
{"M29F400BB", 0x20, 0x22d6, 0x80000, &alg_29_unl}, /* ST */
{"M29F400BB", 0x20, 0x22d5, 0x80000, &alg_29_unl}, /* ST */
{"Am29F080B", 0x01, 0xd5, 0x100000, &alg_29_std}, /* AMD */
{"Am29F800BT", 0x01, 0x22d6, 0x100000, &alg_29_std}, /* AMD */
{"Am29F800BB", 0x01, 0x2258, 0x100000, &alg_29_std}, /* AMD */
{"Am29PL160C", 0x01, 0x2245, 0x200000, &alg_29_unl}, /* AMD */
{"Am29LV160B", 0x01, 0x2249, 0x200000, &alg_29_unl}, /* AMD */
{"M29LV160B", 0x20, 0x2249, 0x200000, &alg_29_unl}, /* ST */
{"HY29LV160B", 0xad, 0x2249, 0x200000, &alg_29_unl}, /* HYRIX */
{"MX29LV160B", 0xc2, 0x2245, 0x200000, &alg_29_unl}, /* MACRONIX */
{"TC58FVB160A", 0x98, 0x0043, 0x200000, &alg_29_unl}, /* TOSHIBA */
{"Am29LV320B", 0x01, 0x22f9, 0x400000, &alg_29_unl}, /* AMD */
{"HY29LV320B", 0xad, 0x227d, 0x400000, &alg_29_unl}, /* HYRIX */
{"MX29LV320B", 0xc2, 0x22a8, 0x400000, &alg_29_unl}, /* MACRONIX */
{"TC58FVM5B2A", 0x98, 0x0055, 0x400000, &alg_29_unl}, /* TOSHIBA */
{"TC58FVM5B3A", 0x98, 0x0050, 0x400000, &alg_29_unl}, /* TOSHIBA */
{"Am29LV640MB", 0x01, 0x227e, 0x800000, &alg_29_unl}, /* AMD */
{"M29W640DB", 0x20, 0x22df, 0x800000, &alg_29_unl}, /* ST */
{"MBM29DLV640E", 0x04, 0x227e, 0x800000, &alg_29_std}, /* FUJITSU */
{"MX29LV640MB", 0xc2, 0x22cb, 0x800000, &alg_29_unl}, /* MACRONIX */
{"TC58FVM6B2A", 0x98, 0x0058, 0x800000, &alg_29_unl}, /* TOSHIBA */
{"Sst39VF1601", 0xbf, 0x234b, 0x200000, &alg_49}, /* SST */
{"Sst39VF1602", 0xbf, 0x234a, 0x200000, &alg_49}, /* SST */
{"Sst39VF3201", 0xbf, 0x235b, 0x400000, &alg_49}, /* SST */
{"Sst39VF3202", 0xbf, 0x235a, 0x400000, &alg_49}, /* SST */
{"Sst39VF6401", 0xbf, 0x236b, 0x800000, &alg_49}, /* SST */
{"Sst39VF6402", 0xbf, 0x236a, 0x800000, &alg_49}, /* SST */
};
/* define the actual access functions to the flash. There are three orthogonal
aspects for the access functions:
1. Every bus_width needs its own set of functions because we need to access
the chips with bus_width width. This is to avoid the access be split up
into several accesses, which could abort a started command.
2. Bus accesses need two functions: one for reading and one for writing.
3. In addition, we need a second set of functions for host-assisted access.
*/
#if HOST_FLASHING
# define DEFINE_READ_FUNC(funcname,vartype,bdmfunc) \
static uint32_t funcname (uint32_t adr) { \
vartype val; \
if (bdmfunc (adr, &val) < 0) \
fprintf (stderr, #bdmfunc "(0x%08lx,xxx): %s\n", \
adr, bdmErrorString()); \
return (uint32_t) val; \
}
# define DEFINE_WRITE_FUNC(funcname,vartype,bdmfunc) \
static void funcname (uint32_t adr, uint32_t val) { \
if (bdmfunc (adr, val) < 0) \
fprintf (stderr, #bdmfunc "(0x%08lx,0x%08x): %s\n", \
adr, val, bdmErrorString()); \
}
#else
# define DEFINE_READ_FUNC(funcname,vartype,bdmfunc) \
static uint32_t funcname (uint32_t adr) { \
return *(volatile vartype *)adr; \
}
# define DEFINE_WRITE_FUNC(funcname,vartype,bdmfunc) \
static void funcname (uint32_t adr,uint32_t val) { \
*(volatile vartype *)adr = val; \
}
#endif
DEFINE_READ_FUNC(chip_rd_char, unsigned char, bdmReadByte)
DEFINE_READ_FUNC(chip_rd_word, unsigned short, bdmReadWord)
DEFINE_READ_FUNC(chip_rd_long, unsigned long, bdmReadLongWord)
DEFINE_WRITE_FUNC(chip_wr_char, uint8_t, bdmWriteByte)
DEFINE_WRITE_FUNC(chip_wr_word, uint16_t, bdmWriteWord)
DEFINE_WRITE_FUNC(chip_wr_long, uint32_t, bdmWriteLongWord)
/* We need a unique symbol to associate a (target-based) plugin with its
(host-based) driver.
*/
static char driver_magic[] = "flash29";
/* Populate the the chiptype structure with bus_width specific information.
This information is redundant. It is maintained here only for
optimizations.
*/
static void
set_chip_access(chiptype_t * ct, uint32_t bus_width)
{
ct->bus_width = bus_width;
switch (bus_width) {
case 1:
ct->shift = 0;
ct->bus_mask = 0x0ff;
ct->wr_func = chip_wr_char;
ct->rd_func = chip_rd_char;
break;
case 2:
ct->shift = 1;
ct->bus_mask = 0x0ffff;
ct->wr_func = chip_wr_word;
ct->rd_func = chip_rd_word;
break;
case 4:
ct->shift = 2;
ct->bus_mask = 0x0ffffffff;
ct->wr_func = chip_wr_long;
ct->rd_func = chip_rd_long;
break;
}
ct->chip_mask = (0x100 << ((ct->chip_width - 1) << 3)) - 1;
}
/* Wait for the chip to complete an erase/program command. Pavel Pisa mentioned
that there's probably a racing condition in this code, so we will need to
take a closer look on this one.
*/
static int
wait_chip(chiptype_t * ct, uint32_t adr, uint32_t expect)
{
uint32_t i;
uint32_t rval;
uint32_t bus_mask = ct->bus_mask;
uint32_t chip_mask = ct->chip_mask;
uint32_t tout_mask = ct->alg_info->timeout_mask;
uint32_t(*rd_func) (uint32_t) = ct->rd_func;
uint32_t last_val = (rd_func(adr) & bus_mask);
while ((rval = (rd_func(adr) & bus_mask)) != (expect & bus_mask)) {
/* We don't want to loop forever when we accidentally try to program an
EPROM. So we expect at least one toggle-bit to change. */
if (last_val == rval)
return 0;
/* loop over chips */
for (i = 0; i < ct->bus_width; i += ct->chip_width) {
/* shift to get bits of this chip onto the lowest bits. */
uint32_t shift = i << 3;
uint32_t shifted_chip_mask = chip_mask << shift;
/* check whether chip i signalled timeout. */
if ((rval >> shift) & tout_mask)
return 0;
/* check whether chip i returned expected data. */
if (!(((rval ^ expect) & shifted_chip_mask))) {
/* Yes, we're not interested in results from this chip anymore. */
bus_mask &= ~shifted_chip_mask;
}
}
last_val = rval;
}
return 1;
}
#if HOST_FLASHING
static char *
prog_entry(void)
{
return "flash29_prog";
}
#endif
/* The actual programming function
*/
static uint32_t
flash29_prog(void *chip_descr,
uint32_t pos, unsigned char *data, uint32_t cnt)
{
uint32_t i, align;
void (*wr_func) (uint32_t, uint32_t);
uint32_t val = 0;
chiptype_t *ct = chip_descr;
uint32_t reg1 = ct->reg1;
uint32_t reg2 = ct->reg2;
uint32_t siz = ct->bus_width;
const alg_info_t *alg_info = ct->alg_info;
uint32_t cmd_bypass = alg_info->cmd_bypass;
uint32_t cmd_reset = alg_info->cmd_reset;
uint32_t cmd_prog = alg_info->cmd_program;
uint32_t cmd_unlock1 = alg_info->cmd_unlock1;
uint32_t cmd_unlock2 = alg_info->cmd_unlock2;
set_chip_access(ct, siz);
wr_func = ct->wr_func;
/* handle unaligned programming */
align = pos & ((1 << (siz - 1)) - 1);;
pos &= ~align;
for (i = 0; i < align; i++) {
val <<= 8;
val |= chip_rd_char(pos + i);
}
if (cmd_bypass) {
wr_func(reg1, cmd_reset);
wr_func(reg1, cmd_unlock1);
wr_func(reg2, cmd_unlock2);
wr_func(reg1, cmd_bypass);
}
i = 0;
#if FLASH_OPTIMIZE_FOR_SPEED
switch (siz) {
# if FLASH_BUS_WIDTH1
case 1:
for (; i < cnt; i++) {
if (!cmd_bypass) {
chip_wr_char(reg1, cmd_reset);
chip_wr_char(reg1, cmd_unlock1);
chip_wr_char(reg2, cmd_unlock2);
}
chip_wr_char(reg1, cmd_prog);
val = *data++;
chip_wr_char(pos, val);
if (!wait_chip(ct, pos, val))
break; /* error out */
pos++;
}
# endif
# if FLASH_BUS_WIDTH2
case 2:
if (align)
goto W1;
while (i < cnt) {
val = (val << 8) | *data++;
W1:val =
(val << 8) | (i++ <
cnt ? *data++ : chip_rd_char(pos + 1));
if (!cmd_bypass) {
chip_wr_word(reg1, cmd_reset);
chip_wr_word(reg1, cmd_unlock1);
chip_wr_word(reg2, cmd_unlock2);
}
chip_wr_word(reg1, cmd_prog);
chip_wr_word(pos, val);
if (!wait_chip(ct, pos, val))
break; /* error out */
pos += 2;
i++;
val = 0;
}
break;
# endif
# if FLASH_BUS_WIDTH4
case 4:
switch (align) {
case 1:
goto L1;
case 2:
goto L2;
case 3:
goto L3;
}
while (i < cnt) {
val = (val << 8) | *data++;
L1:val =
(val << 8) | (i++ <
cnt ? *data++ : chip_rd_char(pos + 1));
L2:val =
(val << 8) | (i++ <
cnt ? *data++ : chip_rd_char(pos + 2));
L3:val =
(val << 8) | (i++ <
cnt ? *data++ : chip_rd_char(pos + 3));
if (!cmd_bypass) {
chip_wr_long(reg1, cmd_reset);
chip_wr_long(reg1, cmd_unlock1);
chip_wr_long(reg2, cmd_unlock2);
}
chip_wr_long(reg1, cmd_prog);
chip_wr_long(pos, val);
if (!wait_chip(ct, pos, val))
break; /* error out */
pos += 4;
i++;
val = 0;
}
break;
# endif
}
#else
while (i < cnt) {
uint32_t j;
for (j = 0; j < siz - align; j++) {
val <<= 8;
val |= i + j < cnt ? *data++ : chip_rd_char(pos + j);
}
if (!cmd_bypass) {
wr_func(reg1, cmd_reset);
wr_func(reg1, cmd_unlock1);
wr_func(reg2, cmd_unlock2);
}
wr_func(reg1, cmd_prog);
wr_func(pos, val);
if (!wait_chip(ct, pos, val))
break; /* error out */
pos += siz;
i += siz;
val = 0;
align = 0;
}
#endif
if (cmd_bypass) {
wr_func(reg1, ct->alg_info->cmd_resbypass1);
wr_func(reg2, ct->alg_info->cmd_resbypass2);
}
return i > cnt ? cnt : i;
}
/* Initiate erase operation. Sector address is relative to chip-base.
With sector address==-1, the whole chip is erased. The erase operation
can be called several times before flash_29_erase_wait() is called for
simultanous erasure of multiple sectors.
*/
static void
flash29_erase(void *chip_descr, int32_t sector_address)
{
chiptype_t *ct = chip_descr;
uint32_t reg1 = ct->reg1;
uint32_t reg2 = ct->reg2;
const alg_info_t *alg_info = ct->alg_info;
void (*wr_func) (uint32_t, uint32_t) = ct->wr_func;
wr_func(reg1, alg_info->cmd_reset);
wr_func(reg1, alg_info->cmd_unlock1);
wr_func(reg2, alg_info->cmd_unlock2);
wr_func(reg1, alg_info->cmd_erase);
wr_func(reg1, alg_info->cmd_unlock1);
wr_func(reg2, alg_info->cmd_unlock2);
if (sector_address >= 0 && sector_address < ct->size) {
ct->wait_adr = ct->adr + (sector_address << ct->shift);
wr_func(ct->wait_adr, alg_info->cmd_secterase);
} else {
ct->wait_adr = ct->adr;
wr_func(reg1, alg_info->cmd_chiperase);
}
}
/* wait for queued erasing operations to finish
*/
static int
flash29_erase_wait(void *chip_descr)
{
chiptype_t *ct = chip_descr;
return wait_chip(ct, ct->wait_adr, ct->bus_mask);
}
#if HOST_FLASHING
/* read the chip ID
*/
static uint32_t
read_id(chiptype_t * ct, int adr)
{
unsigned int ret;
uint32_t reg1 = ct->reg1;
uint32_t reg2 = ct->reg2;
const alg_info_t *alg_info = ct->alg_info;
void (*wr_func) (uint32_t, uint32_t) = ct->wr_func;
wr_func(reg1, alg_info->cmd_reset);
wr_func(reg1, alg_info->cmd_unlock1);
wr_func(reg2, alg_info->cmd_unlock2);
wr_func(reg1, alg_info->cmd_autoselect);
ret = ct->rd_func(ct->adr + (adr << ct->shift));
wr_func(reg1, alg_info->cmd_reset);
return ret;
}
/* autodetect a 29Fxxx type chip
*/
static uint32_t
flash29_search_chip(void *chip_descr, char *description, uint32_t pos)
{
chiptype_t *ct = chip_descr;
int i, j, bw, cw;
uint32_t m, d;
uint32_t exp;
const alg_info_t *alg_info;
const chip_t *chip;
ct->adr = pos;
for (bw = 4; bw; bw >>= 1) {
for (cw = bw; cw; cw >>= 1) {
ct->chip_width = cw;
set_chip_access(ct, bw);
for (i = 0; i < NUMOF(chips); i++) {
chip = &chips[i];
ct->size = chip->size * (bw / cw);
ct->alg_info = alg_info = chip->alg_info;
ct->reg1 = pos + ((alg_info->adr_unlock1) << (ct->shift));
ct->reg2 = pos + ((alg_info->adr_unlock2) << (ct->shift));
if ((m = read_id(ct, 0)) != chip->manufacturer)
continue;
exp = 0;
for (j = 0; j < bw; j += cw) {
exp <<= ((cw - 1) << 3);
exp |= (chip->device_id) & (ct->chip_mask);
}
if ((d = read_id(ct, 1)) != exp)
continue;
/* check if we are just reading ram */
if (m == ct->rd_func(pos) && d == ct->rd_func(pos + (1 << ct->shift)))
return 0;
if (description) {
sprintf(description, "%10s @ 0x%08lx..0x%08lx "
"bw:%d cw:%d manuf:0x%02lx device:0x%04lx size:0x%08lx",
chip->name, pos, pos + ct->size, bw, cw, m, d, ct->size);
}
return ct->size;
}
}
}
return 0;
}
# define CHIP_WR(base,str,field,val) \
chip_wr_long((base)+(((unsigned char*)&((str)->field)) - \
((unsigned char*)str)), \
(val));
/* FIXME: this function assumes that data sizes and alignment requirements
on target and host are identical.
*/
static int
download_struct(void *chip_descr, uint32_t adr)
{
chiptype_t *ct = chip_descr;
const alg_info_t *alg = ct->alg_info;
uint32_t alg_adr = adr + sizeof(*ct);
CHIP_WR(adr, ct, alg_info, alg_adr);
CHIP_WR(adr, ct, adr, ct->adr);
CHIP_WR(adr, ct, size, ct->size);
CHIP_WR(adr, ct, chip_width, ct->chip_width);
CHIP_WR(adr, ct, bus_width, ct->bus_width);
CHIP_WR(adr, ct, reg1, ct->reg1);
CHIP_WR(adr, ct, reg2, ct->reg2);
CHIP_WR(alg_adr, alg, cmd_unlock1, alg->cmd_unlock1);
CHIP_WR(alg_adr, alg, cmd_unlock2, alg->cmd_unlock2);
CHIP_WR(alg_adr, alg, cmd_reset, alg->cmd_reset);
CHIP_WR(alg_adr, alg, cmd_program, alg->cmd_program);
CHIP_WR(alg_adr, alg, cmd_bypass, alg->cmd_bypass);
CHIP_WR(alg_adr, alg, cmd_resbypass1, alg->cmd_resbypass1);
CHIP_WR(alg_adr, alg, cmd_resbypass2, alg->cmd_resbypass2);
CHIP_WR(alg_adr, alg, timeout_mask, alg->timeout_mask);
return alg_adr + sizeof(*alg);
}
void
init_flash29(int num)
{
register_algorithm(num, driver_magic, sizeof(chiptype_t),
download_struct,
flash29_search_chip,
flash29_erase, 0, flash29_erase_wait, flash29_prog,
prog_entry);
}
#else
void
init_flash29(int num)
{
register_algorithm(num, driver_magic, 0, 0, 0,
flash29_erase, 0, flash29_erase_wait, flash29_prog, 0);
}
#endif

47
m68k/flashlib/flash29.h Normal file
View File

@@ -0,0 +1,47 @@
/* $Id: flash29.h,v 1.2 2008/07/31 01:53:44 cjohns Exp $
*
* Header for 29Fxxx and 49Fxxx flash driver.
*
* 2003-12-28 Josef Wolf (jw@raven.inka.de)
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
/* This function will be called by flash_filter and is responsible to register
the driver
*/
void init_flash29(int num);
/* following #define's should probably be set by configure
*/
/* Setting this to 0 produces more generic (and compact) code which is able
to program all bus widths at the expense of performance. Setting this
to 1 approximately doubles the programming speed on a 20MHz 68332 with
Am29F400 in 16-bit-mode.
*/
#define FLASH_OPTIMIZE_FOR_SPEED 0
/* When FLASH_OPTIMIZE_FOR_SPEED==1, selecting only required bus widths can
reduce size of generated code
*/
#define FLASH_BUS_WIDTH1 1
#define FLASH_BUS_WIDTH2 1
#define FLASH_BUS_WIDTH4 1
#if FLASH_OPTIMIZE_FOR_SPEED
# if ( !FLASH_BUS_WIDTH1 && !FLASH_BUS_WIDTH2 && !FLASH_BUS_WIDTH4 )
# error At least one bus width must be defined when FLASH_OPTIMIZE_FOR_SPEED!=0
# endif
#endif

View File

@@ -0,0 +1,654 @@
/* $Id: flash_filter.c,v 1.7 2008/09/09 11:48:50 cjohns Exp $
*
* Flash filtering layer.
*
* 2003-12-28 Josef Wolf (jw@raven.inka.de)
* 2008 Chris Johns (cjohns@users.sourceforge.net)
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
/* This code was inspired by the filtering code from Pavel Pisa. But it was
written from scratch to achieve stronger data encapsulation and enable
target-mode plugins. For the long run, it should be extended for
target-only operation mode.
CCJ : Remove BFD support and replaced with libelf.
*/
#include "flash29.h"
#include "flashcfm.h"
#include "flashintelc3.h"
#include "flash_filter.h"
#if HOST_FLASHING
# include <errno.h>
# include <stdint.h>
# include <stdio.h>
# include <limits.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
# include <elf-utils.h>
# include <BDMlib.h>
#endif
#define mkstring(_s) #_s
/* Interface to flash modules.
*/
typedef struct
{
void (*init) (int);
int struct_size;
char *driver_magic;
int (*download_struct) (void *, uint32_t);
uint32_t (*search_chip) (void *, char *, uint32_t);
void (*erase) (void *, int32_t);
int (*blank_chk) (void *, int32_t);
int (*erase_wait) (void *);
uint32_t (*prog) (void *, uint32_t, unsigned char *, uint32_t);
char *(*prog_entry) (void);
unsigned char *p_code;
uint32_t p_entry;
uint32_t p_len;
uint32_t ram;
uint32_t len;
} alg_t;
/* Known flashing algorithms
*/
alg_t algorithm[] = {
{init_flash29},
{init_flashcfm},
{init_flashintelc3},
};
/* Description of memory areas.
*/
typedef struct area_s
{
uint32_t adr;
uint32_t end; /* last byte inclusive */
alg_t *alg;
void *chip_descriptor;
struct area_s *next;
} area_t;
/* Memory areas. Assume RAM for unregistered areas.
*/
static area_t ram_area = { 0, ~0, NULL, NULL, NULL, };
static area_t *area = NULL;
/* Maximum size of a chip_descriptor. Since the chip-descriptor is algorithm's
internal information, we don't know the size of the descriptor until we
know which algorithm to use. Therefore we need to allocate a maximum size
for autodetection.
*/
static int maxsiz = 0;
/* Variables.
*/
typedef struct variable_s
{
struct variable_s *next;
const char *name;
uint32_t value;
} variable_t;
static variable_t *s_variables = 0;
/* Initialize all known algorithms, determine maximum size of chip descriptors
and register RAM for whole address range.
*/
static void
init (void)
{
int i;
if (area)
return; /* Already initialized */
for (i = 0; i < NUMOF(algorithm); i++) {
algorithm[i].p_code = 0;
algorithm[i].init(i);
if (maxsiz < algorithm[i].struct_size)
maxsiz = algorithm[i].struct_size;
}
area = &ram_area; /* register RAM fallback for whole address range */
}
/* This is the callback for the init functions of the basic flash modules.
Each flash module shall register itself with this function.
Doing it this way keeps algorithm's private data private and minimizes
pollution of namespace.
*/
void
register_algorithm(int num,
char *driver_magic,
int struct_size,
int (*download_struct) (void *, uint32_t),
uint32_t (*search_chip) (void *, char *, uint32_t),
void (*erase) (void *, int32_t),
int (*blank_chk) (void *, int32_t),
int (*erase_wait) (void *),
uint32_t (*prog) (void *, uint32_t, unsigned char *,
uint32_t), char *(*prog_entry) (void))
{
algorithm[num].driver_magic = strdup(driver_magic); /* FIXME */
algorithm[num].struct_size = struct_size;
algorithm[num].download_struct = download_struct;
algorithm[num].search_chip = search_chip;
algorithm[num].erase = erase;
algorithm[num].blank_chk = blank_chk;
algorithm[num].erase_wait = erase_wait;
algorithm[num].prog = prog;
algorithm[num].prog_entry = prog_entry;
algorithm[num].p_code = NULL;
algorithm[num].p_entry = 0;
algorithm[num].p_len = 0;
algorithm[num].ram = 0;
algorithm[num].len = 0;
}
/* Search memory area where ADR belongs to.
*/
static area_t *
search_area (adr)
{
area_t *a;
for (a = area; a; a = a->next)
if (a->adr <= adr && a->end >= adr)
return a;
return NULL;
}
#if HOST_FLASHING
/* register target flash plugins. The adr/len defines a RAM area on the
target that can be used to download plugin and contents.
*/
int
elf_flash_plugin_load(int (*prfunc) (const char *format, ...),
uint32_t adr, uint32_t len, const char *fname)
{
struct stat sb;
elf_handle handle;
const char *dmagic;
const char* prefix = mkstring (PREFIX);
char* name = (char*) fname;
int i;
elf_handle_init(&handle);
if (name[0] != '/')
{
if (stat (name, &sb) < 0)
{
if (errno == ENOENT)
{
if (prefix[strlen (prefix) - 1] != '/')
{
name = strdup (prefix);
name = strcat (name, "/");
}
else
name = strdup (prefix);
name = strcat (name, "share/m68k-bdm/plugins/");
name = strcat (name, fname);
if (stat (name, &sb) < 0)
{
if (errno == ENOENT)
{
prfunc ("cannot find plugin: %s\n", fname);
prfunc ("searched:\n .\n %s: ", mkstring (PREFIX));
return 0;
}
}
}
}
}
if (!elf_open (name, &handle, prfunc))
{
if (prfunc)
prfunc ("open %s failed", name);
return 0;
}
dmagic = elf_get_section_data_sym(&handle, "driver_magic");
if (!dmagic)
{
if (prfunc)
prfunc ("no 'driver_magic' symbol found");
elf_close (&handle);
return 0;
}
for (i = 0; i < NUMOF(algorithm); i++)
{
uint32_t value;
GElf_Sym entrysym;
GElf_Shdr shdr;
void *data;
uint32_t size;
if (!STREQ(dmagic, algorithm[i].driver_magic))
continue;
if (!elf_get_symbol(&handle, algorithm[i].prog_entry(), &entrysym))
{
if (prfunc)
prfunc("could not find prog entry symbol %s",
algorithm[i].prog_entry());
elf_close(&handle);
return 0;
}
if (!elf_get_section_hdr(&handle, entrysym.st_shndx, &shdr))
{
if (prfunc)
prfunc("could not get section header for prog entry");
elf_close(&handle);
return 0;
}
data = elf_get_section_data(&handle, entrysym.st_shndx, &size);
if (!data)
{
if (prfunc)
prfunc("could not get section data for prog entry");
elf_close(&handle);
return 0;
}
algorithm[i].p_entry = entrysym.st_value;
algorithm[i].p_len = size;
algorithm[i].p_code = malloc(size);
memcpy(algorithm[i].p_code, data, size);
algorithm[i].ram = adr;
algorithm[i].len = len;
break;
}
if (prfunc)
{
if (i < NUMOF(algorithm))
prfunc("%s loaded, size:%d", dmagic, algorithm[i].p_len);
else
prfunc("no algorithm %s found", dmagic);
}
elf_close(&handle);
return 1;
}
int
srec_flash_plugin_load(int (*prfunc) (const char *format, ...),
uint32_t adr, uint32_t len, const char *fname)
{
return 0;
}
int
flash_plugin(int (*prfunc) (const char *format, ...),
uint32_t adr, uint32_t len, char *argv[])
{
int cnt;
init();
for (cnt = 0; argv[cnt]; cnt++)
{
if (!elf_flash_plugin_load(prfunc, adr, len, argv[cnt]))
if (!srec_flash_plugin_load(prfunc, adr, len, argv[cnt]))
if (prfunc)
prfunc("no suitable loader found: %s", argv[cnt]);
}
return 0;
}
#endif
static int
prog_clone(area_t * area, uint32_t adr, unsigned char *data, uint32_t size)
{
#if HOST_FLASHING
char driver_magic[1024]; /* FIXME: should be dynamically */
uint32_t mem;
uint32_t len;
static uint32_t entry = 0;
static uint32_t content = 0;
static area_t *last_area = NULL;
uint32_t sp, ra;
uint32_t sent = 0;
uint32_t num;
unsigned long wrote_num = 0;
int cpu_type;
if (!area->alg)
return 0;
if (bdmGetProcessor(&cpu_type) < 0)
return 0;
if (!area->alg->p_code) {
/* No plugin loaded -> use host-only mode. */
return area->alg->prog (area->chip_descriptor, adr, data, size);
}
mem = area->alg->ram;
len = area->alg->len;
if (area != last_area) {
/* Download plugin and chip descriptor into target. */
entry = area->alg->download_struct (area->chip_descriptor, mem);
bdmWriteMemory (entry, area->alg->p_code, area->alg->p_len);
content = entry + area->alg->p_len;
last_area = area;
}
while (sent < size) {
sp = mem + len;
num = sp - 0x200 - content; /* FIXME: stack size should be
determined dynamically */
if (num > size - sent)
num = size - sent;
/* Set up stack frame.
* Be careful with the longword writes, they must be longword aligned!
*/
switch (cpu_type) {
case BDM_CPU32:
sp -= 4;
ra = sp;
bdmWriteWord (sp, 0x4afa); /* BGND instruction */
break;
case BDM_COLDFIRE:
sp -= 4;
ra = sp;
bdmWriteWord (sp, 0x4ac8); /* HALT instruction */
break;
default:
return 0;
}
sp -= 4;
bdmWriteLongWord (sp, num); /* amount of data to flash */
sp -= 4;
bdmWriteLongWord (sp, content); /* adr of memory contents */
sp -= 4;
bdmWriteLongWord (sp, adr); /* destination adr */
sp -= 4;
bdmWriteLongWord (sp, mem); /* chip descriptor */
sp -= 4;
bdmWriteLongWord (sp, ra); /* return address to BGND */
/* Download contents. */
bdmWriteMemory (content, data, num);
/* Set stack pointer and program counter. */
bdmWriteRegister(BDM_REG_A7, sp);
bdmWriteSystemRegister(BDM_REG_RPC, entry + area->alg->p_entry);
/* Execute */
bdmGo();
while (!((bdmStatus ()) & (BDM_TARGETSTOPPED | BDM_TARGETHALT))) ;
bdmReadRegister (BDM_REG_D0, &wrote_num);
if (num != (uint32_t) wrote_num) {
printf ("Returned 0x%08x\n", wrote_num);
break; /* write failed */
}
sent += num;
data += num;
adr += num;
}
#else
/* FIXME: to be done */
#endif
return sent;
}
/* Register a new memory region. The new region should always overlap with
the RAM fallback (which is registered by the init function). The overlap
is resolved by shrinking/splitting the RAM fallback area. Returns 1 on
success, 0 otherwise.
*/
int
flash_register(char *description, uint32_t adr, char *hint_driver)
{
int i;
uint32_t size;
area_t *bold, *new, *aold; /* order is _b_efore, new, _a_fter */
void *chip;
init();
if (!(chip = malloc (maxsiz)))
return 0;
/* Search area where the address belongs to. The result should be the RAM
fallback. */
bold = search_area(adr);
for (i = 0; i < NUMOF(algorithm); i++) {
if (hint_driver != NULL) {
if (!STREQ(hint_driver, algorithm[i].driver_magic))
continue;
}
if ((size = algorithm[i].search_chip(chip, description, adr))) {
if (bold->end > adr + (size - 1)) {
/* End of old area is bigger than end of new area -> add new area of
old style behind new area. */
if (!(aold = malloc(sizeof(*aold))))
break;
*aold = *bold;
aold->adr = adr + size;
aold->next = bold->next;
bold->next = aold;
}
if (bold->adr < adr) {
/* start of old area is less than start of new area -> add new area
of old style in front of new area. */
if (!(new = malloc(sizeof(*new))))
return 0;
new->next = bold->next; /* insert new area into chain */
bold->next = new;
bold->end = adr - 1; /* shrink old area */
} else {
new = bold; /* same start address -> just replace old area */
}
/* fill new area with contents */
new->adr = adr;
new->end = adr + (size - 1);
new->alg = &algorithm[i];
new->chip_descriptor = chip;
return 1;
}
}
free(chip);
return 0;
}
/* Search area of address and call its erase algorithm.
*/
int
flash_erase(uint32_t adr, int32_t sector_offset)
{
area_t *a;
alg_t *alg;
if (!(a = search_area(adr)))
return 0;
if (alg = a->alg) {
if (alg->erase) {
alg->erase(a->chip_descriptor, sector_offset);
return 1;
}
}
return 0;
}
/* Search area of address and call its blank check algorithm.
*/
int
flash_blank_chk(uint32_t adr, int32_t sector_offset)
{
area_t *a;
alg_t *alg;
if (!(a = search_area(adr)))
return 0;
if (alg = a->alg) {
if (alg->blank_chk) {
return alg->blank_chk(a->chip_descriptor, sector_offset);
}
}
return 0;
}
/* Search area of address and call its erase_wait algorithm.
*/
int
flash_erase_wait(uint32_t adr)
{
area_t *a;
alg_t *alg;
if (!(a = search_area(adr)))
return 0;
if (alg = a->alg) {
if (alg->erase_wait) {
return alg->erase_wait(a->chip_descriptor);
}
}
return 0;
}
/* Write to memory through registered algorithms.
*/
uint32_t
write_memory(uint32_t adr, unsigned char *data, uint32_t cnt)
{
uint32_t ret;
uint32_t wrote = 0;
init();
while (wrote < cnt) {
area_t *area = search_area(adr + wrote);
/* That much fits into this area. */
uint32_t size = (area->end - (adr + wrote)) + 1;
/* Limit size if it is more than we actually want to write. */
if (size > cnt - wrote)
size = cnt - wrote;
if (area->alg && area->alg->prog) {
ret = prog_clone(area, adr, data, size);
wrote += ret;
if (ret != size)
return wrote;
} else {
/* no programming algorithm defined, assume RAM */
#if HOST_FLASHING
if (bdmWriteMemory(adr, data, size) < 0)
return wrote;
#else
memcpy((unsigned char *) adr, data, size);
#endif
wrote += size;
}
}
return wrote;
}
int
flash_set_var(const char *name, uint32_t value)
{
/* find and update existing var */
variable_t *var = s_variables;
while(var) {
if(strcmp(var->name, name) == 0) {
var->value = value;
return 1;
}
var = var->next;
}
/* add a new var */
var = (variable_t *) malloc(sizeof(variable_t));
if(!var)
return 0;
var->name = strdup(name);
if(!var->name)
return 0;
var->value = value;
var->next = s_variables;
s_variables = var;
return 1;
}
int
flash_get_var(const char *name, uint32_t *value, uint32_t value_default)
{
variable_t *var = s_variables;
while(var) {
if(strcmp(var->name, name) == 0) {
*value = var->value;
return 1;
}
var = var->next;
}
*value = value_default;
return 0;
}
int
flash_spin(int c)
{
#if HOST_FLASHING
const char spin[] = {'|', '/', '-', '\\'};
int n = c / 100;
printf("\b%c", spin[n % 4]);
fflush(stdout);
#endif
return ++c;
}

View File

@@ -0,0 +1,79 @@
/* $Id: flash_filter.h,v 1.4 2008/07/31 01:53:44 cjohns Exp $
*
* Header for the flash filtering layer.
*
* 2003-12-28 Josef Wolf (jw@raven.inka.de)
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
#ifndef _FLASH_FILTER_H_
# define _FLASH_FILTER_H_
# include <stdint.h>
/* This one should be removed in the long term.
*/
# ifndef HOST_FLASHING
# define HOST_FLASHING 1
# endif
# ifndef STREQ
# define STREQ(a,b) (!strcmp((a),(b)))
# endif
# ifndef NUMOF
# define NUMOF(ary) (sizeof(ary)/sizeof(ary[0]))
# endif
/* A driver need to register itself with this function
*/
void register_algorithm(int num, /* number that was passed to init function */
char *driver_magic,
/* size of the chip description structure */
int struct_size,
/* dnload chip-descr */
int (*download_struct) (void *, uint32_t),
uint32_t (*search_chip) (void *, char *, uint32_t),
void (*erase) (void *, int32_t),
int (*blank_chk) (void *, int32_t),
int (*erase_wait) (void *),
uint32_t (*prog) (void *, uint32_t,
unsigned char *, uint32_t),
/* returns the name of the entry function */
char *(*prog_entry) (void)
);
/* Load target drivers. ADR and LEN define memory region in the target that
can be used for downloading code/data.
*/
int flash_plugin (int (*prfunc) (const char *format, ...),
uint32_t adr, uint32_t len, char *argv[]);
/* Register a flash chip on ADR
*/
int flash_register (char *description, uint32_t adr, char *hint_driver);
int flash_erase (uint32_t adr, int32_t sec_adr);
int flash_blank_chk (uint32_t adr, int32_t sec_adr);
int flash_erase_wait (uint32_t adr);
uint32_t write_memory (uint32_t adr, unsigned char *data, uint32_t cnt);
int flash_set_var (const char *name, uint32_t value);
int flash_get_var (const char *name, uint32_t *value, uint32_t value_default);
int flash_spin (int c);
#endif

364
m68k/flashlib/flashcfm.c Normal file
View File

@@ -0,0 +1,364 @@
/* $Id:
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
#include "flashcfm.h"
#include "flash_filter.h"
#include <stdint.h>
#if HOST_FLASHING
# include <stdio.h>
# include <BDMlib.h>
# include <string.h>
#endif
#define MCF_CFM_CFMCLKD_DIVLD (0x80)
#define MCF_CFM_CFMUSTAT_BLANK (0x04)
#define MCF_CFM_CFMUSTAT_CCIF (0x40)
#define MCF_CFM_CFMUSTAT_CBEIF (0x80)
#define MCF_CFM_CFMCMD_BLANK_CHECK (0x5)
#define MCF_CFM_CFMCMD_PAGE_ERASE_VERIFY (0x6)
#define MCF_CFM_CFMCMD_WORD_PROGRAM (0x20)
#define MCF_CFM_CFMCMD_PAGE_ERASE (0x40)
#define MCF_CFM_CFMCMD_MASS_ERASE (0x41)
/*
* Warning! do not change this struct without changing the download_struct
* function.
*/
typedef struct
{
uint32_t backdoor_address_start;
uint32_t backdoor_address_end;
uint32_t flash_address;
uint32_t flash_size;
uint32_t ipsbar;
uint32_t cfmclkd;
uint32_t cfmustat;
uint32_t cfmcmd;
} chiptype_t;
#if HOST_FLASHING
static inline uint8_t
read_byte(uint32_t a_addr)
{
unsigned char result;
if (bdmReadByte(a_addr, &result) < 0)
fprintf(stderr, "read_byte(0x%08x): %s\n", a_addr, bdmErrorString());
return (uint8_t) result;
}
static inline uint16_t
read_word(uint32_t a_addr)
{
unsigned short result;
if (bdmReadWord(a_addr, &result) < 0)
fprintf(stderr, "read_word(0x%08x): %s\n", a_addr, bdmErrorString());
return (uint16_t) result;
}
static inline uint32_t
read_longword(uint32_t a_addr)
{
unsigned long result;
if (bdmReadLongWord(a_addr, &result) < 0)
fprintf(stderr, "read_longword(0x%08x): %s\n", a_addr, bdmErrorString());
return (uint32_t) result;
}
static inline void
write_byte(uint32_t a_addr, uint8_t a_x)
{
if (bdmWriteByte(a_addr, a_x) < 0)
fprintf(stderr, "write_byte(0x%08x): %s\n", a_addr, bdmErrorString());
}
static inline void
write_word(uint32_t a_addr, uint16_t a_x)
{
if (bdmWriteWord(a_addr, a_x) < 0)
fprintf(stderr, "write_word(0x%08x): %s\n", a_addr, bdmErrorString());
}
static inline void
write_longword(uint32_t a_addr, uint32_t a_x)
{
if (bdmWriteLongWord(a_addr, a_x) < 0)
fprintf(stderr, "write_longword(0x%08x): %s\n", a_addr, bdmErrorString());
}
#else
# define read_byte(A) (*((volatile uint8_t *) (A)))
# define read_word(A) (*((volatile uint16_t *) (A)))
# define read_longword(A) (*((volatile uint32_t *) (A)))
# define write_byte(A, B) *((volatile uint8_t *)(A)) = (B)
# define write_word(A, B) *((volatile uint16_t *)(A)) = (B)
# define write_longword(A, B) *((volatile uint32_t *)(A)) = (B)
#endif
static inline uint32_t
swap32(uint32_t a_v)
{
return (uint32_t) (((a_v >> 24) & 0x000000ff) | ((a_v << 24) & 0xff000000) |
((a_v >> 8) & 0x0000ff00) | ((a_v << 8) & 0x00ff0000));
}
static inline int
is_little_endian(void)
{
uint32_t i = 1;
return (int) *((uint8_t *) &i);
}
/* We need a unique symbol to associate a (target-based) plugin with its
(host-based) driver.
*/
static char driver_magic[] = "flashcfm";
#if HOST_FLASHING
static char *
prog_entry(void)
{
return "flashcfm_prog";
}
#endif
/* The actual programming function.
* NOTE: pos and cnt need to be 4 byte aligned!
*/
static uint32_t
flashcfm_prog(void *chip_descr,
uint32_t pos, unsigned char *data, uint32_t cnt)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
uint32_t offset = ct->backdoor_address_start + (pos - ct->flash_address);
uint32_t n = 0;
cnt /= 4;
if (read_byte(ct->cfmclkd) & MCF_CFM_CFMCLKD_DIVLD) {
while (!(read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_CBEIF)) {
}
for (n = 0; n < cnt; ++n) {
uint32_t d = ((uint32_t *) data)[n];
/* write_longword on host assumes host endianess so will perform a
* byte order swap if host is little endian. we need to swap if little
* endian such that the swap will just swap back to the correct endianess
*/
if(is_little_endian())
d = swap32(d);
write_longword(offset + n * 4, d);
write_byte(ct->cfmcmd, MCF_CFM_CFMCMD_WORD_PROGRAM);
write_byte(ct->cfmustat, MCF_CFM_CFMUSTAT_CBEIF);
if (read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_CBEIF) {
continue;
}
while (!(read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_CCIF)) {
}
}
}
return n * 4;
}
/* Initiate erase operation. Sector address is relative to chip-base.
With sector address==-1, the whole chip is erased. The erase operation
can be called several times before flash_29_erase_wait() is called for
simultanous erasure of multiple sectors.
*/
static void
flashcfm_erase(void *chip_descr, int32_t sector_address)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
if (read_byte(ct->cfmclkd) & MCF_CFM_CFMCLKD_DIVLD) {
while (!(read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_CBEIF)) {
}
if (sector_address == -1) {
write_longword(ct->backdoor_address_start, 0);
write_byte(ct->cfmcmd, MCF_CFM_CFMCMD_MASS_ERASE);
} else {
write_longword(ct->backdoor_address_start +
(sector_address - ct->flash_address), 0);
write_byte(ct->cfmcmd, MCF_CFM_CFMCMD_PAGE_ERASE);
}
write_byte(ct->cfmustat, MCF_CFM_CFMUSTAT_CBEIF);
}
}
/* Blank check operation. Sector address is relative to chip-base.
With sector address==-1, the whole chip is checked.
*/
static int
flashcfm_blank_chk(void *chip_descr, int32_t sector_address)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
int result = 0;
if (read_byte(ct->cfmclkd) & MCF_CFM_CFMCLKD_DIVLD) {
while (!(read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_CBEIF)) {
}
if (sector_address == -1) {
write_longword(ct->backdoor_address_start, 0);
write_byte(ct->cfmcmd, MCF_CFM_CFMCMD_BLANK_CHECK);
} else {
write_longword(ct->backdoor_address_start +
(sector_address - ct->flash_address), 0);
write_byte(ct->cfmcmd, MCF_CFM_CFMCMD_PAGE_ERASE_VERIFY);
}
write_byte(ct->cfmustat, MCF_CFM_CFMUSTAT_CBEIF);
while (!(read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_CCIF)) {
}
if (read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_BLANK) {
result = 1;
write_byte(ct->cfmustat, MCF_CFM_CFMUSTAT_BLANK);
}
}
return result;
}
/* wait for queued erasing operations to finish
*/
static int
flashcfm_erase_wait(void *chip_descr)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
#if HOST_FLASHING
int spin = 0;
#endif
if (read_byte(ct->cfmclkd) & MCF_CFM_CFMCLKD_DIVLD) {
while (!(read_byte(ct->cfmustat) & MCF_CFM_CFMUSTAT_CCIF)) {
#if HOST_FLASHING
spin = flash_spin(spin);
#endif
}
return 1;
}
return 0;
}
#if HOST_FLASHING
/* autodetect
*/
static uint32_t
flashcfm_search_chip(void *chip_descr, char *description, uint32_t pos)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
unsigned long flashbar = 0;
uint32_t fbar_reg;
flash_get_var("%flashbar", &fbar_reg, 0x0c04);
if (bdmReadControlRegister(fbar_reg, &flashbar) >= 0) {
if ((flashbar & 1) && ((flashbar & 0xfff80000) == pos)) {
flash_get_var("IPSBAR", &ct->ipsbar, 0x40000000);
flash_get_var("FLASH_BACKDOOR", &ct->backdoor_address_start, 0x04000000);
flash_get_var("FLASH_SIZE", &ct->flash_size, 256 * 1024);
ct->backdoor_address_start += ct->ipsbar;
ct->backdoor_address_end = ct->backdoor_address_start +
ct->flash_size;
flash_get_var("MCF_CFM_CFMCLKD", &ct->cfmclkd, 0x1D0002);
flash_get_var("MCF_CFM_CFMUSTAT", &ct->cfmustat, 0x1D0020);
flash_get_var("ct->cfmcmd", &ct->cfmcmd, 0x1D0024);
ct->cfmclkd += ct->ipsbar;
ct->cfmustat += ct->ipsbar;
ct->cfmcmd += ct->ipsbar;
ct->flash_address = pos;
if (description) {
sprintf(description, "Coldfire flash module @ 0x%08lx..0x%08lx "
"size:0x%08lx",
pos, pos + ct->flash_size, ct->flash_size);
}
return ct->flash_size;
}
}
return 0;
}
static int
download_struct(void *chip_descr, uint32_t adr)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
bdmWriteLongWord(adr, ct->backdoor_address_start);
adr += 4;
bdmWriteLongWord(adr, ct->backdoor_address_end);
adr += 4;
bdmWriteLongWord(adr, ct->flash_address);
adr += 4;
bdmWriteLongWord(adr, ct->flash_size);
adr += 4;
bdmWriteLongWord(adr, ct->ipsbar);
adr += 4;
bdmWriteLongWord(adr, ct->cfmclkd);
adr += 4;
bdmWriteLongWord(adr, ct->cfmustat);
adr += 4;
bdmWriteLongWord(adr, ct->cfmcmd);
adr += 4;
return adr;
}
void
init_flashcfm(int num)
{
register_algorithm(num, driver_magic, sizeof(chiptype_t),
download_struct,
flashcfm_search_chip,
flashcfm_erase,
flashcfm_blank_chk,
flashcfm_erase_wait, flashcfm_prog, prog_entry);
}
#else
void
init_flashcfm(int num)
{
register_algorithm(num, driver_magic, 0,
0,
0,
flashcfm_erase,
flashcfm_blank_chk,
flashcfm_erase_wait, flashcfm_prog, 0);
}
#endif

44
m68k/flashlib/flashcfm.h Normal file
View File

@@ -0,0 +1,44 @@
/* $Id:
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
/*
* To use the flashcfm algorithm:
*
* set the following flash varialbes (flash_set_var)
*
* varname (default) note
* IPSBAR (0x40000000)
* MCF_CFM_CFMCLKD (0x1D0002) ipsbar offset
* MCF_CFM_CFMUSTAT (0x1D0020) ipsbar offset
* MCF_CFM_CFMCMD (0x1D0024) ipsbar offset
* FLASHBAR_REG (0x0C04)
* FLASH_SIZE (256 * 1024)
* FLASH_BACKDOOR (0x04000000) ipsbar offset
*
* NOTE: The target and flash clock must be setup to the correct flashing
* frequency prior to invoking this flash algorithm
*
* NOTE: Flash detection simply checks flashbar, so flashbar must be configured
* prior to calling flash_register
*
* NOTE: Flash addresses and write memory sizes need to be 4 byte aligned!
*
*/
/* This function will be called by flash_filter and is responsible to register
the driver
*/
void init_flashcfm(int num);

View File

@@ -0,0 +1,416 @@
/* $Id:
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
#include "flashintelc3.h"
#include "flash_filter.h"
#include <stdint.h>
#if HOST_FLASHING
# include <stdio.h>
# include <BDMlib.h>
# include <string.h>
#endif
typedef struct
{
const char *name;
const uint32_t manufacturer, device_id;
const uint32_t size; /* in bytes */
const uint32_t num_sectors;
const uint32_t top;
} chip_t;
/*
* Warning! do not change this struct without changing the download_struct
* function.
*/
typedef struct
{
uint32_t flash_address;
uint32_t flash_size;
uint32_t num_sectors;
uint32_t top;
} chiptype_t;
static const chip_t chips[] = {
{"28F800C3T", 0x0089, 0x88C0, 0x100000, 23, 1}, /* INTEL */
{"28F800C3B", 0x0089, 0x88C1, 0x100000, 23, 0}, /* INTEL */
{"28F160C3T", 0x0089, 0x88C2, 0x200000, 39, 1}, /* INTEL */
{"28F160C3B", 0x0089, 0x88C3, 0x200000, 39, 0}, /* INTEL */
{"28F320C3T", 0x0089, 0x88C4, 0x400000, 71, 1}, /* INTEL */
{"28F320C3B", 0x0089, 0x88C5, 0x400000, 71, 0}, /* INTEL */
{"28F640C3T", 0x0089, 0x88CC, 0x800000, 135, 1}, /* INTEL */
{"28F640C3B", 0x0089, 0x88CD, 0x800000, 135, 0}, /* INTEL */
};
#if HOST_FLASHING
# define DEFINE_READ_FUNC(funcname,vartype,bdmfunc) \
static uint32_t funcname (uint32_t adr) { \
vartype val; \
if (bdmfunc (adr, &val) < 0) \
fprintf (stderr, #bdmfunc "(0x%08lx,xxx): %s\n", \
adr, bdmErrorString()); \
return (uint32_t) val; \
}
# define DEFINE_WRITE_FUNC(funcname,vartype,bdmfunc) \
static void funcname (uint32_t adr, uint32_t val) { \
if (bdmfunc (adr, val) < 0) \
fprintf (stderr, #bdmfunc "(0x%08lx,0x%08x): %s\n", \
adr, val, bdmErrorString()); \
}
#else
# define DEFINE_READ_FUNC(funcname,vartype,bdmfunc) \
static uint32_t funcname (uint32_t adr) { \
return *(volatile vartype *)adr; \
}
# define DEFINE_WRITE_FUNC(funcname,vartype,bdmfunc) \
static void funcname (uint32_t adr,uint32_t val) { \
*(volatile vartype *)adr = val; \
}
#endif
static inline uint16_t
swap16(uint16_t a_v)
{
return (uint16_t) (((a_v >> 8) & 0x00ff) | ((a_v << 8) & 0xff00));
}
static inline int
is_little_endian(void)
{
uint32_t i = 1;
return (int) *((uint8_t *) &i);
}
DEFINE_READ_FUNC(chip_rd_word, unsigned short, bdmReadWord)
DEFINE_WRITE_FUNC(chip_wr_word, uint16_t, bdmWriteWord)
/* We need a unique symbol to associate a (target-based) plugin with its
(host-based) driver.
*/
static char driver_magic[] = "flashintelc3";
#if HOST_FLASHING
static char *
prog_entry(void)
{
return "flashintelc3_prog";
}
#endif
static uint32_t
flashintelc3_sector_size(chiptype_t* chip, int sector)
{
if(chip->top) {
if(sector < (chip->num_sectors - 8)) {
return 0x10000;
}
else {
return 0x2000;
}
}
else {
if(sector < 8) {
return 0x2000;
}
else {
return 0x10000;
}
}
}
static uint32_t
flashintelc3_sector_offset(chiptype_t* chip, int sector)
{
if(chip->top) {
uint32_t d = chip->num_sectors - 8;
if(sector < d) {
return 0x10000 * sector;
}
else {
return (0x10000 * d) + (0x2000 * (sector - d));
}
}
else {
if(sector < 8) {
return 0x2000 * sector;
}
else {
return 0x10000 + (0x10000 * (sector - 8));
}
}
}
/* 0=unlock, 1=lock */
static void
flashintelc3_lock(void *chip_descr, uint32_t start, uint32_t bytes, int cmd)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
int i, s = 0, e = 0;
int ucmd = (cmd) ? 0x01 : 0xD0;
if(bytes == 0)
return;
/* find start sector */
for(i = 0; i < ct->num_sectors; ++i) {
uint32_t off = flashintelc3_sector_offset(ct, i);
uint32_t size = flashintelc3_sector_size(ct, i);
if((start >= ct->flash_address + off) &&
(start < ct->flash_address + off + size)) {
s = i;
break;
}
}
/* find end */
for(; i < ct->num_sectors; ++i) {
uint32_t off = flashintelc3_sector_offset(ct, i);
uint32_t size = flashintelc3_sector_size(ct, i);
if(start + bytes <= ct->flash_address + off + size) {
e = i;
break;
}
}
/* unlock range */
for(i = s; i <= e; ++i) {
uint32_t off = flashintelc3_sector_offset(ct, i);
chip_wr_word(ct->flash_address + off, 0x60);
chip_wr_word(ct->flash_address + off, ucmd);
}
}
/* The actual programming function.
* NOTE: pos and cnt need to be 2 byte aligned!
*/
static uint32_t
flashintelc3_prog(void *chip_descr,
uint32_t pos, unsigned char *data, uint32_t cnt)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
uint32_t n = 0;
uint16_t status;
flashintelc3_lock(ct, pos, cnt, 0);
cnt /= 2;
for (n = 0; n < cnt; ++n) {
uint16_t d = ((uint16_t *) (void*) data)[n];
chip_wr_word(pos, 0x40);
/* write_word on host assumes host endianess so will perform a
* byte order swap if host is little endian. we need to swap if little
* endian such that the swap will just swap back to the correct endianess
*/
if(is_little_endian())
d = swap16(d);
chip_wr_word(pos, d);
/*
* Wait for program operation to finish
*/
do {
chip_wr_word(pos, 0x70);
status = chip_rd_word(pos);
}
while (!(status & 0x80));
pos += 2;
}
chip_wr_word(ct->flash_address, 0xff);
return n * 2;
}
static void
flashintelc3_erase(void *chip_descr, int32_t sector_address)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
uint16_t status;
int i;
#if HOST_FLASHING
int spin = 0;
#endif
if(sector_address == -1) {
flashintelc3_lock(ct, ct->flash_address, ct->flash_size, 0);
/* erasing all sectors */
for(i = 0; i < ct->num_sectors; ++i) {
uint32_t off = flashintelc3_sector_offset(ct, i);
chip_wr_word(ct->flash_address + off, 0x20);
chip_wr_word(ct->flash_address + off, 0xD0);
/* wait */
do {
chip_wr_word(ct->flash_address + off, 0x70);
status = chip_rd_word(ct->flash_address + off);
#if HOST_FLASHING
spin = flash_spin(spin);
#endif
} while(!(status & 0x80));
}
}
else {
uint32_t off = flashintelc3_sector_offset(ct, sector_address);
flashintelc3_lock(ct, ct->flash_address + off, 1, 0);
/* erasing said sector address */
chip_wr_word(ct->flash_address + off, 0x20);
chip_wr_word(ct->flash_address + off, 0xD0);
/* wait */
do {
chip_wr_word(ct->flash_address + off, 0x70);
status = chip_rd_word(ct->flash_address + off);
#if HOST_FLASHING
spin = flash_spin(spin);
#endif
} while(!(status & 0x80));
}
chip_wr_word(ct->flash_address, 0xff);
}
/* Blank check operation. Sector address is relative to chip-base.
With sector address==-1, the whole chip is checked.
*/
static int
flashintelc3_blank_chk(void *chip_descr, int32_t sector_address)
{
#if HOST_FLASHING
printf("intelc3: blank_chk not implemented!\n");
#endif
return 0;
}
/* wait for queued erasing operations to finish
*/
static int
flashintelc3_erase_wait(void *chip_descr)
{
#if HOST_FLASHING
printf("intelc3: no wait needed!\n");
#endif
return 0;
}
#if HOST_FLASHING
# ifndef NUMOF
# define NUMOF(ary) (sizeof(ary)/sizeof(ary[0]))
# endif
/* autodetect
*/
static uint32_t
flashintelc3_search_chip(void *chip_descr, char *description, uint32_t pos)
{
uint32_t size = 0;
uint32_t m, d;
chiptype_t *ct = (chiptype_t *) chip_descr;
const chip_t *chip;
int i;
/* read the manufacturer id */
chip_wr_word(pos, 0x90);
m = chip_rd_word(pos + 0);
/* read the device id */
chip_wr_word(pos, 0x90);
d = chip_rd_word(pos + 2);
/* find our device */
for (i = 0; i < NUMOF(chips); i++) {
chip = &chips[i];
if(chip->manufacturer == m && chip->device_id == d) {
ct->flash_address = pos;
ct->flash_size = chip->size;
ct->num_sectors = chip->num_sectors;
ct->top = chip->top;
size = chip->size;
if (description) {
sprintf(description, "%10s @ 0x%08lx..0x%08lx "
"manuf:0x%02lx device:0x%04lx size:0x%08lx",
chip->name, pos, pos + chip->size, m, d, chip->size);
}
break;
}
}
/* put the device back into read mode */
chip_wr_word(pos, 0xff);
return size;
}
static int
download_struct(void *chip_descr, uint32_t adr)
{
chiptype_t *ct = (chiptype_t *) chip_descr;
bdmWriteLongWord(adr, ct->flash_address);
adr += 4;
bdmWriteLongWord(adr, ct->flash_size);
adr += 4;
bdmWriteLongWord(adr, ct->num_sectors);
adr += 4;
bdmWriteLongWord(adr, ct->top);
adr += 4;
return adr;
}
void
init_flashintelc3(int num)
{
register_algorithm(num, driver_magic, sizeof(chiptype_t),
download_struct,
flashintelc3_search_chip,
flashintelc3_erase,
flashintelc3_blank_chk,
flashintelc3_erase_wait, flashintelc3_prog, prog_entry);
}
#else
void
init_flashintelc3(int num)
{
register_algorithm(num, driver_magic, 0,
0,
0,
flashintelc3_erase,
flashintelc3_blank_chk,
flashintelc3_erase_wait, flashintelc3_prog, 0);
}
#endif

View File

@@ -0,0 +1,32 @@
/* $Id:
*
* Portions of this program which I authored may be used for any purpose
* so long as this notice is left intact.
*
* 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.
*/
/*
* To use the flashintelc3 algorithm:
*
* NOTE: You'll need to setup any chip selects etc.
*
* NOTE: No need to use an erase wait command for batch erases. if doing
* a sector erase you'll need to do an erase followed by an erase wait!
*
* NOTE: Flash addresses and write memory sizes need to be 4 byte aligned!
*
*/
/* This function will be called by flash_filter and is responsible to register
the driver
*/
void init_flashintelc3(int num);

View File

@@ -0,0 +1,21 @@
#! /bin/sh
CC=$1 # The m68k cross compiler.
SRC=$2 # The source file.
OUTPUT=$3 # The output file. Contains the CPU.
CPU=$(echo $OUTPUT | sed -e 's/.*-//g' -e 's/\..*//g')
PWARN="-pedantic -Wall -Wcast-align -Wstrict-prototypes -Wmissing-prototypes"
POPT="-O2 -fomit-frame-pointer"
PREL="-mpcrel"
PDEF="-DHOST_FLASHING=0"
PTGT="-mcpu=$CPU"
OPT="$PWARN $POPT $PREL $PDEF $PTGT"
CMD="$CC $OPT -c -o $OUTPUT $SRC"
echo $CMD
$CMD
exit $?