diff options
Diffstat (limited to 'ecos/packages/devs/flash/amd')
10 files changed, 5861 insertions, 0 deletions
diff --git a/ecos/packages/devs/flash/amd/am29xxxxx/current/ChangeLog b/ecos/packages/devs/flash/amd/am29xxxxx/current/ChangeLog new file mode 100644 index 0000000..c2e2130 --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxx/current/ChangeLog @@ -0,0 +1,384 @@ +2010-07-14 Christophe Coutand <ecos@hotmail.co.uk> + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_AM29LV640M]: + * cdl/flash_amd_am29xxxxx.cdl: Add AM29LV640M part + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_S29GL512P]: + * cdl/flash_amd_am29xxxxx.cdl: Add Spansion S29GL512P part + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_S29GL01GP]: + * cdl/flash_amd_am29xxxxx.cdl: Add Spansion S29GL01GP part + +2009-02-17 Lars Povlsen <lpovlsen@vitesse.com> + + * include/flash_am29xxxxx_parts.inl: + Added Macronix MX29LV128M B part (8- and 16-bit) + Added Macronix MX29LV128M T part (8-bit) + Added Spansion S29GL128N part (8-bit) + +2009-02-16 RenĂ© Schipp von Branitz Nielsen <rbn@vitesse.com> + + * include/flash_am29xxxxx.inl: Silence warning with use of + CYGHWR_DEVS_FLASH_ST_M29W320D. + +2008-11-17 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/flash_amd_am29xxxxx.cdl: Indicate that this driver uses + the legacy flash device API. + +2006-11-28 Oyvind Harboe <oyvind.harboe@zylin.com> + + * Fixed boot sectors for ST M29W320D + +2006-08-29 Yoshinori Sato <ysato@users.sourceforge.jp> + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_S29GL128M]: + * cdl/flash_amd_am29xxxxx.cdl: Add AMD/SPANSION S29GL128M part + +2005-08-11 Oyvind Harboe <oyvind.harboe@zylin.com> + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_ST_M29W320D]: + * cdl/flash_amd_am29xxxxx.cdl: Add ST M29W320D part. + +2006-04-03 Lars Povlsen <lpovlsen@vitesse.com> + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_MX29LV128]: + * cdl/flash_amd_am29xxxxx.cdl: Add MXIC MX29LV128 part. + + * include/flash_am29xxxxx.inl: (find_sector) Fixed dealing with + bootblocks. Was returning device block size even for boot blocks. + +2006-02-15 Stephane Deltour <stephane.deltour@barco.com> + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_S29GL128N]: + * cdl/flash_amd_am29xxxxx.cdl: Add AMD/SPANSION S29GL128N part. + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_S29GL256N]: + * cdl/flash_amd_am29xxxxx.cdl: Add AMD/SPANSION S29GL256N part. + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_S29GL512N]: + * cdl/flash_amd_am29xxxxx.cdl: Add AMD/SPANSION S29GL512N part. + +2005-09-08 Peter Korsgaard <jacmet@sunsite.dk> + + * include/flash_am29xxxxx.inl (flash_program_buf): Handle writes + with length not a multiple of flash word size. + +2005-04-17 David Vrabel <dvrabel@arcom.com> + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_AM29F002T]: + * cdl/flash_amd_am29xxxxx.cdl: Add AMD AM29F002T part. + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_AM29LV256]: + * cdl/flash_amd_am29xxxxx.cdl: Add AMD AM29LV256 part. + + * include/flash_am29xxxxx_parts.inl [CYGHWR_DEVS_FLASH_AMD_AM29LV128]: + Use long device id for AM29LV128 part. + +2005-03-18 Peter Korsgaard <jacmet@sunsite.dk> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_S29PL032J, + CYGHWR_DEVS_FLASH_AMD_S29PL064J, CYGHWR_DEVS_FLASH_AMD_S29PL127J): + * cdl/flash_amd_am29xxxxx.cdl: Add support for Spansion S29PL032J, + S29PL064J and S29PL127J parts. + +2005-02-20 Kurt Stremerch <kurt.stremerch@exys.be> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_S29GL064M): + * cdl/flash_amd_am29xxxxx.cdl: Add support for the S29GL064M part. + +2004-04-21 Sebastien Couret <sebastien.couret@elios-informatique.com> + + * include/flash_am29xxxxx.inl: Minor changes to silence warnings. + +2004-04-08 Bob Koninckx <bob.koninckx@o-3s.com> + * include/flash_am29xxxxx_parts.inl: Added support for AM29PL160 top + boot block devices and corrected typo. + +2004-04-06 Gary Thomas <gary@mlbassoc.com> + + * include/flash_am29xxxxx.inl (flash_program_buf): Buffered program + writes failed when configured for parallel devices. + +2003-10-21 Jay Foster <jay@systech.com> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_AM29LV033C): + Fixed device definition to allow erasing of the upper half of the + device. The Sector Protect Verify command would erroneously report + the upper half of the device as locked. + +2003-10-02 Jay Foster <jay@systech.com> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_AM29LV081B, + CYGHWR_DEVS_FLASH_AMD_AM29LV017D, CYGHWR_DEVS_FLASH_AMD_AM29LV033C, + CYGHWR_DEVS_FLASH_AMD_AM29LV065D): + * cdl/flash_amd_am29xxxxx.cdl: Add support for Am29LV081B, Am29LV017D, + Am29LV033C, and Am29LV065D parts. + +2003-09-09 Thomas Koeller <thomas.koeller@baslerweb.com> + + * include/flash_am29xxxxx.inl: + * include/flash_am29xxxxx_parts.inl: Added support for write + buffer programming. + +2003-09-04 Thomas Koeller <thomas.koeller@baslerweb.com> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_AM29LV128): + * cdl/flash_amd_am29xxxxx.cdl: Add support for Am29LV128 part. + +2003-08-17 Bart Veer <bartv@ecoscentric.com> + + * include/flash_am29xxxxx.inl: + Allow platform-specific code to override the default loop counts + used for timeouts. + + * include/flash_am29xxxxx_parts.inl, cdl/flash_amd_am29xxxxx.cdl: + Add AM29PL160 device + +2003-07-23 Chris Garry <cgarry@sweeneydesign.co.uk> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_AM29LV400): + * cdl/flash_amd_am29xxxxx.cdl: Add support for Am29LV400 part. + +2003-04-03 Jani Monoses <jani@iv.ro> + + * include/flash_am29xxxxx.inl: + Removed wrapper functions which enabled/disabled cache around query, + erase and program operations since the generic flash driver takes + care of the cache already. + +2003-02-11 Gary Thomas <gary@mlbassoc.com> + + * include/flash_am29xxxxx_parts.inl: + Fix identifier code for AM29LV320DT. + +2002-12-23 Patrick Doyle <wpd@delcomsys.com> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_AM29DL640D): + * cdl/flash_amd_am29xxxxx.cdl: + Add support for AM29DL323 and for 16 bit operation of the + AM29DL322. + +2002-12-04 Mark Salter <msalter@redhat.com> + + * include/flash_am29xxxxx_parts.inl: + * cdl/flash_amd_am29xxxxx.cdl: Add support for AM29DL322. + +2002-11-25 Gary Thomas <gthomas@ecoscentric.com> + + * include/flash_am29xxxxx_parts.inl (CYGHWR_DEVS_FLASH_AMD_AM29DL640D): + Now tested in 16 bit configurations. + + * include/flash_am29xxxxx.inl: Fix problems with CYGNUM_FLASH_16AS8. + The definition was inconsistent/confusing. + +2002-11-17 Bob Koninckx <bob.koninckx@mech.kuleuven.ac.be> + + * include/flash_am29xxxxx_parts.inl: + * cdl/flash_am29xxxxx.cdl: Definition for AM29F010 part added. Used by cme555. + +2002-10-11 Gary Thomas <gary@mlbassoc.com> + + * include/flash_am29xxxxx_parts.inl: + * include/flash_am29xxxxx.inl: Better support for devices with + "bootblock" sections - some newer devices have more than one! + +2002-09-26 Ian Campbell <icampbell@arcomcontrols.com> + + * include/flash_am29xxxxx_parts.inl: + * cdl/flash_amd_am29xxxxx.cdl: Add support for AM29DL640D. + + * include/flash_am29xxxxx.inl: Add support for triple byte part id + numbers, such as those used by the AM29DL640D. Allow for parts + with up to 5 banks, rather than two -- also to support AM29DL640D + parts. + +2002-07-29 Gary Thomas <gary@chez-thomas.org> +2002-07-29 Motoya Kurotsu <kurotsu@allied-telesis.co.jp> + + * include/flash_am29xxxxx.inl: Force routines which actually use + the FLASH to run from RAM. + +2002-07-24 Gary Thomas <gary@chez-thomas.org> +2002-07-24 Motoya Kurotsu <kurotsu@allied-telesis.co.jp> + + * include/flash_am29xxxxx.inl (_flash_program_buf): Fix data + type for 'state' - needs to be flash_data_t. + +2002-06-20 Gary Thomas <gary@chez-thomas.org> + + * include/flash_am29xxxxx.inl: Add cache disable/enable code + since this is required on most platforms. + + * include/flash_am29xxxxx_parts.inl: + * cdl/flash_amd_am29xxxxx.cdl: Add support for AM29LV320D{T|B} + +2002-04-24 Bob Koninckx <bob.koninckx@mech.kuleuven.ac.be> + + * cdl/flash_amd_am29xxxxx.cdl: Support AM29LV200 and ST M29W200B. + * include/flash_am29xxxxx_parts.inl: Likewise. + +2002-01-03 Jonathan Larmour <jlarmour@redhat.com> +2001-12-20 Koichi Nagashima <naga@r-lab.co.jp> + + * cdl/flash_amd_am29xxxxx.cdl: Add support for Toshiba TC58FVB800 part. + * include/flash_am29xxxxx_parts.inl: Ditto. + + * include/flash_am29xxxxx.inl: Fix FLASH_Reset definition. + Check sector erase timer correctly. + +2001-10-31 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx_parts.inl: Removed fix me comments - + description is accurate. + +2001-10-30 Jesper Skov <jskov@redhat.com> + From Gary: + * include/flash_am29xxxxx_parts.inl: Added preliminary AM29LV640 + support. Still needs some tweaks. + * cdl/flash_amd_am29xxxxx.cdl: Same. + +2001-09-26 Gary Thomas <gthomas@redhat.com> + + * include/flash_am29xxxxx.inl (flash_erase_block): + New platform control - CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT. + Define this if the write-protect feature is non-functional/missing. + +2001-08-16 Jonathan Larmour <jlarmour@redhat.com> + + * include/flash_am29xxxxx.inl: Double erase timeouts for faster CPUs. + +2001-08-10 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx.inl (flash_hwr_init): Fix block number. + +2001-07-26 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx.inl: Made code deal with multiple + banks. Use flag to identify banked devices. + * include/flash_am29xxxxx_parts.inl: Updated with banked flag. + +2001-07-23 David Howells <dhowells@redhat.com> + + * include/flash_am29xxxxx.inl: Added support for chips divided + into banks, and added correct addresses for 16-bit chips + configured in 8-bit mode + * include/flash_am29xxxxx_parts.inl: Added data for chips divided + into banks + +2001-06-11 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx.inl: Traverse by incrementing + driver-global pointer variable. + +2001-06-11 David Howells <dhowells@redhat.com> + + * include/flash_am29xxxxx.inl: actually traverse the list of + supported devices, rather than checking the first entry several + times + +2001-06-08 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx_parts.inl: New file with just part + data. + + * include/flash_am29xxxxx.inl: Leave more space for bootblock + offsets. Moved part table data to separate file. + + * cdl/flash_amd_am29xxxxx.cdl: Added config options to control + inclusion of table data for various parts. + +2001-05-29 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx.inl (flash_hwr_init): Call platform init + code if defined. + +2001-05-28 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx.inl: Rewritten to handle bootblock + parts, autodetect part and configure accordingly. + Fixed erase and program code to work with devices in parallel. + Fixed buglet in bootblock detect code. + +2001-05-23 Jesper Skov <jskov@redhat.com> + + * cdl/flash_amd_am29xxxxx.cdl: Links function in RAM. IO driver + need not copy. + + * include/flash_am29xxxxx.inl: Check for WP before trying to erase + block. Use P2V macro. + +2001-02-23 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx.inl (flash_query): Allow device to + settle before returning. + +2001-02-22 Jesper Skov <jskov@redhat.com> + + * include/flash_am29xxxxx.inl: Fix typo. Cleaned up, almost + working with MBX. Times out when erasing from ROM version of RB. + +2001-02-20 Jesper Skov <jskov@redhat.com> + + * .../amd/am29xxxxx: Cloned from hardwired am29f040b driver. + +2000-12-07 Jesper Skov <jskov@redhat.com> + + * src/flash.h: Addresses and sizes are also affected by + interleaving. + * src/flash_erase_block.c: Plug in working loop. + * src/flash_program_buf.c: Same. + +2000-12-06 Jesper Skov <jskov@redhat.com> + + * src/am29f040b_flash.c (flash_hwr_init): Use new query semantics. + * src/flash_query.c (flash_query): Changed accordingly. + + * src/flash.h (FLASH_Sector_Erase_Timer): Added. + + * src/flash_erase_block.c: Do not check error flag after operation + completes. + * src/flash_program_buf.c: Same. + +2000-12-05 Jonathan Larmour <jlarmour@redhat.com> + + * src/am29f040b_flash.c (flash_code_overlaps): Define stext/etext + as array types so no assumptions can be made by the compiler about + location. + +2000-12-05 Jesper Skov <jskov@redhat.com> + + * Cloned from MBX driver. + +2000-10-20 Gary Thomas <gthomas@redhat.com> + + * src/mbx_flash.c: + * src/flash_query.c: + * src/flash_program_buf.c: + * src/flash_erase_block.c: + * src/flash.h: + * cdl/flash_mbx.cdl: New package/file(s). + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc. +// +// 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 or (at your option) any +// later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., 51 Franklin Street, +// Fifth Floor, Boston, MA 02110-1301, USA. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/ecos/packages/devs/flash/amd/am29xxxxx/current/cdl/flash_amd_am29xxxxx.cdl b/ecos/packages/devs/flash/amd/am29xxxxx/current/cdl/flash_amd_am29xxxxx.cdl new file mode 100644 index 0000000..73642bc --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxx/current/cdl/flash_amd_am29xxxxx.cdl @@ -0,0 +1,429 @@ +# ==================================================================== +# +# flash_amd_am29xxxxx.cdl +# +# FLASH memory - Hardware support for AMD AM29xxxxx parts +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. +## +## eCos 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 or (at your option) any later +## version. +## +## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): gthomas +# Contributors: gthomas, jskov, Koichi Nagashima +# Date: 2001-02-20 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX { + display "AMD AM29XXXXX FLASH memory support" + description "FLASH memory device support for AMD AM29XXXXX" + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + + active_if CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED + + implements CYGHWR_IO_FLASH_DEVICE + implements CYGHWR_IO_FLASH_DEVICE_LEGACY + + include_dir cyg/io + + requires { CYGINT_DEVS_FLASH_AMD_VARIANTS != 0 } + + cdl_interface CYGINT_DEVS_FLASH_AMD_VARIANTS { + display "Number of included variants" + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29F002T { + display "AMD AM29F002T flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29F002T (top boot block) + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29F010 { + display "AMD AM29F010 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29F010 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29F040B { + display "AMD AM29F040B flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29F040B + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV128 { + display "AMD AM29LV128 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV128 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_MX29LV128 { + display "MXIC MX29LV128 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the MX29LV128 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV160 { + display "AMD AM29LV160 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV160 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29PL160 { + display "AMD AM29PL160 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29PL160 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV320D { + display "AMD AM29LV320 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV320 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_ST_M29W320D { + display "ST M29W320D flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the ST M29W320D + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV200 { + display "AMD AM29LV200 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV200 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_ST_M29W200B { + display "ST M29W200B flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the ST M29W200B part. This + memory device is pin- and software compatible with the + AMD AM29LV200 device." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV640 { + display "AMD AM29LV640 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV640 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29DL322D { + display "AMD AM29DL322D flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29DL322D + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29DL323D { + display "AMD AM29DL323D flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29DL323D + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29DL324D { + display "AMD AM29DL324D flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29DL324D + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV400 { + display "AMD AM29LV400 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29LV400 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29DL640D { + display "AMD AM29DL640D flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29DL640D + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV640M { + display "AMD AM29LV640M flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29LV640M + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29F800 { + display "AMD AM29F800 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29F800 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV800 { + display "AMD AM29LV800 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AM29LV800 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_TC58FVB800 { + display "Toshiba TC58FVB800 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the Toshiba TC58FVB800." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV081B { + display "AMD AM29LV081B flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV081B + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV017D { + display "AMD AM29LV017D flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV017D + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV033C { + display "AMD AM29LV033C flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV033C + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV065D { + display "AMD AM29LV065D flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD29LV065D + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_AM29LV256 { + display "AMD AM29LV256 flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the AMD AM29LV256 + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29GL064M { + display "AMD/SPANSION S29GL064M flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD/SPANSION flash driver will be + able to recognize and handle the S29GL064M + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29PL032J { + display "Spansion S29PL032J flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the S29PL032J + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29PL064J { + display "Spansion S29PL064J flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the S29PL064J + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29PL127J { + display "Spansion S29PL127J flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD flash driver will be + able to recognize and handle the S29PL0127J + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29GL128N { + display "AMD/SPANSION S29GL128N flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD/SPANSION flash driver will be + able to recognize and handle the S29GL128N + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29GL256N { + display "AMD/SPANSION S29GL256N flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD/SPANSION flash driver will be + able to recognize and handle the S29GL256N + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29GL512N { + display "AMD/SPANSION S29GL512N flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD/SPANSION flash driver will be + able to recognize and handle the S29GL512N + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29GL128M { + display "AMD/SPANSION S29GL128M flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD/SPANSION flash driver will be + able to recognize and handle the S29GL128M + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29GL512P { + display "AMD/SPANSION S29GL512P flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD/SPANSION flash driver will be + able to recognize and handle the S29GL512P + part in the family." + } + + cdl_option CYGHWR_DEVS_FLASH_AMD_S29GL01GP { + display "AMD/SPANSION S29GL01GP flash memory support" + default_value 0 + implements CYGINT_DEVS_FLASH_AMD_VARIANTS + description " + When this option is enabled, the AMD/SPANSION flash driver will be + able to recognize and handle the S29GL01GP + part in the family." + } + +} diff --git a/ecos/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx.inl b/ecos/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx.inl new file mode 100644 index 0000000..9f5d236 --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx.inl @@ -0,0 +1,633 @@ +#ifndef CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL +#define CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL +//========================================================================== +// +// am29xxxxx.inl +// +// AMD AM29xxxxx series flash driver +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas, jskov, Koichi Nagashima +// Date: 2001-02-21 +// Purpose: +// Description: AMD AM29xxxxx series flash device driver +// Notes: While the parts support sector locking, some only do so +// via crufty magic and the use of programmer hardware +// (specifically by applying 12V to one of the address +// pins) so the driver does not support write protection. +// +// FIXME: Should support SW locking on the newer devices. +// +// FIXME: Figure out how to do proper error checking when there are +// devices in parallel. Presently the driver will return +// driver timeout error on device errors which is not very +// helpful. +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/devs_flash_amd_am29xxxxx.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_misc.h> +#include CYGHWR_MEMORY_LAYOUT_H + +#define _FLASH_PRIVATE_ +#include <cyg/io/flash.h> + +//---------------------------------------------------------------------------- +// Common device details. +#define FLASH_Read_ID FLASHWORD( 0x90 ) +#define FLASH_WP_State FLASHWORD( 0x90 ) +#define FLASH_Reset FLASHWORD( 0xF0 ) +#define FLASH_Program FLASHWORD( 0xA0 ) +#define FLASH_Block_Erase FLASHWORD( 0x30 ) +#define FLASH_Load_Buffer FLASHWORD( 0x25 ) +#define FLASH_Flush_Buffer FLASHWORD( 0x29 ) + +#define FLASH_Data FLASHWORD( 0x80 ) // Data complement +#define FLASH_Busy FLASHWORD( 0x40 ) // "Toggle" bit +#define FLASH_Err FLASHWORD( 0x20 ) +#define FLASH_Sector_Erase_Timer FLASHWORD( 0x08 ) + +#define FLASH_unlocked FLASHWORD( 0x00 ) + +#ifndef CYGNUM_FLASH_16AS8 +#define _16AS8 0 +#else +#define _16AS8 CYGNUM_FLASH_16AS8 +#endif + + +# if (_16AS8 == 0) || defined(CYGHWR_DEVS_FLASH_ST_M29W320D) +# define FLASH_Setup_Addr1 (0x555) +# define FLASH_Setup_Addr2 (0x2AA) +# define FLASH_VendorID_Addr (0) +# define FLASH_DeviceID_Addr (1) +# define FLASH_DeviceID_Addr2 (0x0e) +# define FLASH_DeviceID_Addr3 (0x0f) +# define FLASH_WP_Addr (2) +#else +# define FLASH_Setup_Addr1 (0xAAA) +# define FLASH_Setup_Addr2 (0x555) +# define FLASH_VendorID_Addr (0) +# define FLASH_DeviceID_Addr (2) +# define FLASH_DeviceID_Addr2 (0x1c) +# define FLASH_DeviceID_Addr3 (0x1e) +# define FLASH_WP_Addr (4) +#endif + +#define FLASH_Setup_Code1 FLASHWORD( 0xAA ) +#define FLASH_Setup_Code2 FLASHWORD( 0x55 ) +#define FLASH_Setup_Erase FLASHWORD( 0x80 ) + +// Platform code must define the below +// #define CYGNUM_FLASH_INTERLEAVE : Number of interleaved devices (in parallel) +// #define CYGNUM_FLASH_SERIES : Number of devices in series +// #define CYGNUM_FLASH_WIDTH : Width of devices on platform +// #define CYGNUM_FLASH_BASE : Address of first device + +// Platform code may define some or all of the below, to provide +// timeouts appropriate to the target hardware. The timeout +// values depend partly on the flash part being used, partly +// on the target (including bus and cpu speeds). +#ifndef CYGNUM_FLASH_TIMEOUT_QUERY +# define CYGNUM_FLASH_TIMEOUT_QUERY 500000 +#endif +#ifndef CYGNUM_FLASH_TIMEOUT_ERASE_TIMER +# define CYGNUM_FLASH_TIMEOUT_ERASE_TIMER 10000000 +#endif +#ifndef CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE +# define CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE 10000000 +#endif +#ifndef CYGNUM_FLASH_TIMEOUT_PROGRAM +# define CYGNUM_FLASH_TIMEOUT_PROGRAM 10000000 +#endif + +#define CYGNUM_FLASH_BLANK (1) + +#ifndef FLASH_P2V +# define FLASH_P2V( _a_ ) ((volatile flash_data_t *)((CYG_ADDRWORD)(_a_))) +#endif +#ifndef CYGHWR_FLASH_AM29XXXXX_PLF_INIT +# define CYGHWR_FLASH_AM29XXXXX_PLF_INIT() +#endif + +//---------------------------------------------------------------------------- +// Now that device properties are defined, include magic for defining +// accessor type and constants. +#include <cyg/io/flash_dev.h> + +//---------------------------------------------------------------------------- +// Information about supported devices +typedef struct flash_dev_info { + cyg_bool long_device_id; + flash_data_t device_id; + flash_data_t device_id2; + flash_data_t device_id3; + cyg_uint32 block_size; + cyg_int32 block_count; + cyg_uint32 base_mask; + cyg_uint32 device_size; + cyg_bool bootblock; + cyg_uint32 bootblocks[64]; // 0 is bootblock offset, 1-11 sub-sector sizes (or 0) + cyg_bool banked; + cyg_uint32 banks[8]; // bank offsets, highest to lowest (lowest should be 0) + // (only one entry for now, increase to support devices + // with more banks). + cyg_uint32 bufsiz; // write buffer size in units of flash_data_t +} flash_dev_info_t; + +static const flash_dev_info_t* flash_dev_info; +static const flash_dev_info_t supported_devices[] = { +#include <cyg/io/flash_am29xxxxx_parts.inl> +}; +#define NUM_DEVICES (sizeof(supported_devices)/sizeof(flash_dev_info_t)) + +//---------------------------------------------------------------------------- +// Functions that put the flash device into non-read mode must reside +// in RAM. +void flash_query(void* data) __attribute__ ((section (".2ram.flash_query"))); +int flash_erase_block(void* block, unsigned int size) + __attribute__ ((section (".2ram.flash_erase_block"))); +int flash_program_buf(void* addr, void* data, int len) + __attribute__ ((section (".2ram.flash_program_buf"))); + +//---------------------------------------------------------------------------- +// Auxiliary functions +static volatile flash_data_t * find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo) + __attribute__ ((section (".2ram.find_bank"))); +static flash_data_t * find_sector(volatile flash_data_t * addr, unsigned long *remain_size) + __attribute__ ((section (".2ram.find_sector"))); + +//---------------------------------------------------------------------------- +// Flash Query +// +// Only reads the manufacturer and part number codes for the first +// device(s) in series. It is assumed that any devices in series +// will be of the same type. + +void +flash_query(void* data) +{ + volatile flash_data_t *ROM; + volatile flash_data_t *f_s1, *f_s2; + flash_data_t* id = (flash_data_t*) data; + flash_data_t w; + long timeout = CYGNUM_FLASH_TIMEOUT_QUERY; + + ROM = (flash_data_t*) CYGNUM_FLASH_BASE; + f_s1 = FLASH_P2V(ROM+FLASH_Setup_Addr1); + f_s2 = FLASH_P2V(ROM+FLASH_Setup_Addr2); + + *f_s1 = FLASH_Reset; + w = *(FLASH_P2V(ROM)); + + *f_s1 = FLASH_Setup_Code1; + *f_s2 = FLASH_Setup_Code2; + *f_s1 = FLASH_Read_ID; + + id[0] = -1; + id[1] = -1; + + // Manufacturers' code + id[0] = *(FLASH_P2V(ROM+FLASH_VendorID_Addr)); + // Part number + id[1] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr)); + id[2] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr2)); + id[3] = *(FLASH_P2V(ROM+FLASH_DeviceID_Addr3)); + + + *(FLASH_P2V(ROM)) = FLASH_Reset; + + // Stall, waiting for flash to return to read mode. + while ((--timeout != 0) && (w != *(FLASH_P2V(ROM)))) ; +} + + +//---------------------------------------------------------------------------- +// Initialize driver details +int +flash_hwr_init(void) +{ + flash_data_t id[4]; + int i; + + CYGHWR_FLASH_AM29XXXXX_PLF_INIT(); + + flash_dev_query(id); + + // Look through table for device data + flash_dev_info = supported_devices; + for (i = 0; i < NUM_DEVICES; i++) { + if (!flash_dev_info->long_device_id && flash_dev_info->device_id == id[1]) + break; + else if ( flash_dev_info->long_device_id && flash_dev_info->device_id == id[1] + && flash_dev_info->device_id2 == id[2] + && flash_dev_info->device_id3 == id[3] ) + break; + flash_dev_info++; + } + + // Did we find the device? If not, return error. + if (NUM_DEVICES == i) + return FLASH_ERR_DRV_WRONG_PART; + + // Hard wired for now + flash_info.block_size = flash_dev_info->block_size; + flash_info.blocks = flash_dev_info->block_count * CYGNUM_FLASH_SERIES; + flash_info.start = (void *)CYGNUM_FLASH_BASE; + flash_info.end = (void *)(CYGNUM_FLASH_BASE+ (flash_dev_info->device_size * CYGNUM_FLASH_SERIES)); + return FLASH_ERR_OK; +} + +//---------------------------------------------------------------------------- +// Map a hardware status to a package error +int +flash_hwr_map_error(int e) +{ + return e; +} + + +//---------------------------------------------------------------------------- +// See if a range of FLASH addresses overlaps currently running code +bool +flash_code_overlaps(void *start, void *end) +{ + extern unsigned char _stext[], _etext[]; + + return ((((unsigned long)&_stext >= (unsigned long)start) && + ((unsigned long)&_stext < (unsigned long)end)) || + (((unsigned long)&_etext >= (unsigned long)start) && + ((unsigned long)&_etext < (unsigned long)end))); +} + +//---------------------------------------------------------------------------- +// Erase Block + +int +flash_erase_block(void* block, unsigned int size) +{ + volatile flash_data_t* ROM, *BANK; + volatile flash_data_t* b_p = (flash_data_t*) block; + volatile flash_data_t *b_v; + volatile flash_data_t *f_s0, *f_s1, *f_s2; + int timeout = CYGNUM_FLASH_TIMEOUT_QUERY; + int len = 0; + int res = FLASH_ERR_OK; + flash_data_t state; + cyg_bool bootblock = false; + cyg_uint32 *bootblocks = (cyg_uint32 *)0; + CYG_ADDRWORD bank_offset; + ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask); + BANK = find_bank(ROM, block, &bank_offset); + + f_s0 = FLASH_P2V(BANK); + f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1); + f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2); + + // Assume not "boot" sector, full size + bootblock = false; + len = flash_dev_info->block_size; + + // Is this in a "boot" sector? + if (flash_dev_info->bootblock) { + bootblocks = (cyg_uint32 *)&flash_dev_info->bootblocks[0]; + while (*bootblocks != _LAST_BOOTBLOCK) { + if (*bootblocks++ == ((unsigned long)block - (unsigned long)ROM)) { + len = *bootblocks++; // Size of first sub-block + bootblock = true; + break; + } else { + int ls = flash_dev_info->block_size; + // Skip over segment + while ((ls -= *bootblocks++) > 0) ; + } + } + } + + while (size > 0) { +#ifndef CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT + // First check whether the block is protected + *f_s1 = FLASH_Setup_Code1; + *f_s2 = FLASH_Setup_Code2; + *f_s1 = FLASH_WP_State; + state = *FLASH_P2V(b_p+FLASH_WP_Addr); + *f_s0 = FLASH_Reset; + + if (FLASH_unlocked != state) + return FLASH_ERR_PROTECT; +#endif + + b_v = FLASH_P2V(b_p); + + // Send erase block command - six step sequence + *f_s1 = FLASH_Setup_Code1; + *f_s2 = FLASH_Setup_Code2; + *f_s1 = FLASH_Setup_Erase; + *f_s1 = FLASH_Setup_Code1; + *f_s2 = FLASH_Setup_Code2; + *b_v = FLASH_Block_Erase; + + // Now poll for the completion of the sector erase timer (50us) + timeout = CYGNUM_FLASH_TIMEOUT_ERASE_TIMER; // how many retries? + while (true) { + state = *b_v; + if ((state & FLASH_Sector_Erase_Timer) + == FLASH_Sector_Erase_Timer) break; + + if (--timeout == 0) { + res = FLASH_ERR_DRV_TIMEOUT; + break; + } + } + + // Then wait for erase completion. + if (FLASH_ERR_OK == res) { + timeout = CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE; + while (true) { + state = *b_v; + if (FLASH_BlankValue == state) { + break; + } + + // Don't check for FLASH_Err here since it will fail + // with devices in parallel because these may finish + // at different times. + + if (--timeout == 0) { + res = FLASH_ERR_DRV_TIMEOUT; + break; + } + } + } + + if (FLASH_ERR_OK != res) + *FLASH_P2V(ROM) = FLASH_Reset; + + size -= len; // This much has been erased + + // Verify erase operation + while (len > 0) { + b_v = FLASH_P2V(b_p++); + if (*b_v != FLASH_BlankValue) { + // Only update return value if erase operation was OK + if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; + return res; + } + len -= sizeof(*b_p); + } + + if (bootblock) { + len = *bootblocks++; + } + } + return res; +} + + +//---------------------------------------------------------------------------- +// Program Buffer +int +flash_program_buf(void* addr, void* data, int len) +{ + volatile flash_data_t* ROM; + volatile flash_data_t* BANK; + volatile flash_data_t* SECT=NULL; + volatile flash_data_t* data_ptr = (volatile flash_data_t*) data; + volatile flash_data_t* addr_p = (flash_data_t*) addr; + volatile flash_data_t* addr_v = FLASH_P2V(addr_p); + volatile flash_data_t *f_s1, *f_s2; + CYG_ADDRWORD bank_offset; + int timeout; + int res = FLASH_ERR_OK; + const CYG_ADDRWORD mask = + flash_dev_info->bufsiz * sizeof (flash_data_t) - 1; + unsigned long rem_sect_size; + int remain; + + // check the address is suitably aligned + if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1)) + return FLASH_ERR_INVALID; + + // Base address of device(s) being programmed. + ROM = (volatile flash_data_t*)((unsigned long)addr_p & flash_dev_info->base_mask); + BANK = find_bank(ROM, addr, &bank_offset); + + f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1); + f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2); + rem_sect_size = 0; + remain = len % sizeof (flash_data_t); + len /= sizeof (flash_data_t); + + while (len > 0) { + flash_data_t state; + unsigned int nwords; + + addr_v = FLASH_P2V(addr_p); + + if (flash_dev_info->bufsiz > 1) { + // Assume buffer size is power of two + unsigned int i; + + if (rem_sect_size == 0) { + SECT = find_sector(addr_v, &rem_sect_size); + rem_sect_size /= sizeof (flash_data_t); + } + + // Compute word count to write + nwords = flash_dev_info->bufsiz + - (((CYG_ADDRWORD) addr_v & mask) / sizeof (flash_data_t)); + if (nwords > len) + nwords = len; + + // Initiate buffered write + *f_s1 = FLASH_Setup_Code1; + *f_s2 = FLASH_Setup_Code2; + *SECT = FLASH_Load_Buffer; + *SECT = FLASHWORD(nwords - 1); // All devices need to see this + + // Load data into write buffer, flush buffer + for(i = 0; i < nwords; i++) + *addr_v++ = *data_ptr++; + --addr_v; --data_ptr; + *SECT = FLASH_Flush_Buffer; + rem_sect_size -= nwords; + } else { + // Program data [byte] - 4 step sequence + *f_s1 = FLASH_Setup_Code1; + *f_s2 = FLASH_Setup_Code2; + *f_s1 = FLASH_Program; + *addr_v = *data_ptr; + + nwords = 1; + } + + addr_p += nwords; + timeout = CYGNUM_FLASH_TIMEOUT_PROGRAM; + while (true) { + state = *addr_v; + if (*data_ptr == state) { + break; + } + + // Can't check for FLASH_Err since it'll fail in parallel + // configurations. + + if (--timeout == 0) { + res = FLASH_ERR_DRV_TIMEOUT; + break; + } + } + + if (FLASH_ERR_OK != res) + *FLASH_P2V(ROM) = FLASH_Reset; + + if (*addr_v != *data_ptr++) { + // Only update return value if erase operation was OK + if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; + break; + } + len -= nwords; + } + + // Program remaining bytes if len not a multiple of flash word size + if ((FLASH_ERR_OK == res) && remain) + { + // construct final word to be programmed with 0xff in the + // remaining bytes + flash_data_t final = (flash_data_t)-1; + unsigned char *src = (unsigned char *) data_ptr; + unsigned char *dst = (unsigned char *) &final; + + while (remain--) + *dst++ = *src++; + + addr_v = FLASH_P2V(addr_p); + + // Program data [byte] - 4 step sequence + *f_s1 = FLASH_Setup_Code1; + *f_s2 = FLASH_Setup_Code2; + *f_s1 = FLASH_Program; + *addr_v = final; + + timeout = CYGNUM_FLASH_TIMEOUT_PROGRAM; + while (true) { + flash_data_t state = *addr_v; + if (final == state) { + break; + } + + // Can't check for FLASH_Err since it'll fail in parallel + // configurations. + + if (--timeout == 0) { + res = FLASH_ERR_DRV_TIMEOUT; + break; + } + } + + if (FLASH_ERR_OK != res) + *FLASH_P2V(ROM) = FLASH_Reset; + + if (*addr_v != final) { + // Only update return value if write operation was OK + if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY; + } + } + + // Ideally, we'd want to return not only the failure code, but also + // the address/device that reported the error. + return res; +} + +static volatile flash_data_t * +find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo) +{ + volatile flash_data_t * res = base; + + if (flash_dev_info->banked) { + int b = 0; + *bo = (unsigned long)addr & ~(flash_dev_info->block_size-1); + *bo -= (unsigned long) base; + for(;;) { + if (*bo >= flash_dev_info->banks[b]) { + res = (volatile flash_data_t*) ((unsigned long)base + flash_dev_info->banks[b]); + break; + } + b++; + } + } + + return res; +} + +static flash_data_t * +find_sector(volatile flash_data_t * addr, unsigned long *remain_size) +{ + const CYG_ADDRESS mask = flash_dev_info->block_size - 1; + const CYG_ADDRESS a = (CYG_ADDRESS) addr; + const CYG_ADDRESS base = a & flash_dev_info->base_mask; + CYG_ADDRESS res = a & ~mask; + + *remain_size = flash_dev_info->block_size - (a & mask); + + if (flash_dev_info->bootblock) { + cyg_uint32 * bootblocks = flash_dev_info->bootblocks; + while (*bootblocks != _LAST_BOOTBLOCK) { + if (*bootblocks++ == (res - base)) { /* Matching offset marker */ + while (res + *bootblocks <= a) { + res += *bootblocks++; + } + *remain_size = *bootblocks - (a - res); + break; + } else { + int ls = flash_dev_info->block_size; + // Skip over segment + while ((ls -= *bootblocks++) > 0) ; + } + } + } + + return (flash_data_t *) res; +} + +#endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL diff --git a/ecos/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx_parts.inl b/ecos/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx_parts.inl new file mode 100644 index 0000000..d9c2ae1 --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxx/current/include/flash_am29xxxxx_parts.inl @@ -0,0 +1,1547 @@ +#ifndef CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_PARTS_INL +#define CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_PARTS_INL +//========================================================================== +// +// am29xxxxx_parts.inl +// +// AMD AM29xxxxx part descriptors +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2009 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): jskov +// Contributors: jskov, Koichi Nagashima +// Date: 2001-06-08 +// Purpose: +// Description: AMD AM29xxxxx part descriptors +// Usage: Should be included from the flash_am29xxxxx.inl file only. +// +// FIXME: Add configury for selecting bottom/top bootblocks +//####DESCRIPTIONEND#### +// +//========================================================================== + +// +// Note: 'bootblocks' are a set of blocks which are treated by +// the driver as a single larger block. This simplifies the driver +// so as to only have to deal with single size blocks (even though +// the physical device may differ). The data structure is laid out as: +// <address of start of boot block area 1> +// <size of sub-block 1> +// <size of sub-block 2> +// ... +// <size of sub-block n> +// <address of start of boot block area 2> +// <size of sub-block 1> +// <size of sub-block 2> +// ... +// <size of sub-block n> +// _LAST_BOOTBLOCK +// +// Finally, when specifying a device with bootblocks, the total number +// of blocks should reflect this collapse, i.e. if the device has 15 +// full size blocks and 8 blocks which are 1/8 each, then the total +// should be 16 blocks. +// +#define _LAST_BOOTBLOCK (-1) + +#if CYGNUM_FLASH_WIDTH == 8 +#ifdef CYGHWR_DEVS_FLASH_AMD_MX29LV128 + { // MX29LV128M-B (Bottom-boot) + long_device_id: true, + device_id : FLASHWORD(0x7e), + device_id2 : FLASHWORD(0x11), + device_id3 : FLASHWORD(0x00), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 32 + }, + { // MX29LV128M-T (Top-boot) + long_device_id: true, + device_id : FLASHWORD(0x7e), + device_id2 : FLASHWORD(0x11), + device_id3 : FLASHWORD(0x01), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0xff0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 32 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29F002T + { // AM29F002T + device_id : FLASHWORD(0xb0), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 4, + device_size: 0x40000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x40000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x030000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29F010 + { // AM29F010 + device_id : FLASHWORD(0x20), + block_size : 0x4000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 8, + device_size: 0x20000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x20000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29F040B + { // AM29F040B + device_id : FLASHWORD(0xa4), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 8, + device_size: 0x80000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x80000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV160 + { // MBM29LV160-T | AM29LV160-T + device_id : FLASHWORD(0xc4), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 32, + device_size: 0x200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x1f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // MBM29LV160-B | AM29LV160-B + device_id : FLASHWORD(0x49), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 32, + device_size: 0x200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV200 + { // AM29LV200-T + device_id : FLASHWORD(0x3b), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 4, + device_size: 0x40000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x40000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x030000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29LV200-B + device_id : FLASHWORD(0xbf), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 4, + device_size: 0x40000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x40000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV320D + { // AM29LV320DT + device_id : FLASHWORD(0xF6), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29LV320D + device_id : FLASHWORD(0xF9), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL322D + { // AM29DL322D-T + device_id : FLASHWORD(0x55), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x380000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, + { // AM29DL322D-B + device_id : FLASHWORD(0x56), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x80000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL323D + { // AM29DL323D-T + device_id : FLASHWORD(0x50), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x300000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, + { // AM29DL323D-B + device_id : FLASHWORD(0x53), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x100000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL324D + { // AM29DL324D-T + device_id : FLASHWORD(0x5c), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x200000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, + { // AM29DL324D-B + device_id : FLASHWORD(0x5f), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x200000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL640D +{ // AM29DL640D + long_device_id: true, + device_id : FLASHWORD(0x7e), + device_id2 : FLASHWORD(0x02), + device_id3 : FLASHWORD(0x01), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x0800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x8000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x7F0000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x0700000 * CYGNUM_FLASH_INTERLEAVE, + 0x0400000 * CYGNUM_FLASH_INTERLEAVE, + 0x0100000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29F800 + { // AM29F800-T + device_id : FLASHWORD(0xd6), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0xf0000 * CYGNUM_FLASH_INTERLEAVE, + 0x08000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x04000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29F800-B + device_id : FLASHWORD(0x58), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV800 + { // AM29LV800-T + device_id : FLASHWORD(0xda), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0xf0000 * CYGNUM_FLASH_INTERLEAVE, + 0x08000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x04000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29LV800-B + device_id : FLASHWORD(0x5b), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_TC58FVB800 + { // Toshiba TC58FVB800 (compatible with AM29LV800-B except for IDs.) + device_id : FLASHWORD(0xCE), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV081B + { // AM29LV081B + device_id : FLASHWORD(0x38), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 1 + }, +#endif + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV017D + { // AM29LV017D + device_id : FLASHWORD(0xC8), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 32, + device_size: 0x200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 1 + }, +#endif + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV033C + { // AM29LV033C + device_id : FLASHWORD(0xA3), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + // Although this device is not a true banked device, we + // treat the device as having two banks to get the + // Sector Protect Verify to work for the upper half of + // the device. Reference Note 9 for Table 9 in the + // AMD data sheet. + banked : true, + banks : { 0x200000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV065D + { // AM29LV065D + device_id : FLASHWORD(0x93), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x800000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 1 + }, +#endif + +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL128N + { // AMD/SPANSION S29GL128N + long_device_id: true, + device_id : FLASHWORD(0x7e), + device_id2 : FLASHWORD(0x21), + device_id3 : FLASHWORD(0x01), + block_size : 0x20000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 32, + }, +#endif + +#else // 16 bit devices + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV128 + { // AM29LV128 + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2212), + device_id3 : FLASHWORD(0x2200), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 16 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_MX29LV128 + { // MX29LV128M-B + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2211), + device_id3 : FLASHWORD(0x2200), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 16 + }, + { // MX29LV128M-T + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2211), + device_id3 : FLASHWORD(0x2201), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0xff0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 16 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV160 + { // MBM29LV160-T | AM29LV160-T + device_id : FLASHWORD(0x22c4), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 32, + device_size: 0x200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x1f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // MBM29LV160-B | AM29LV160-B + device_id : FLASHWORD(0x2249), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 32, + device_size: 0x200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29PL160 + { // AM29PL160-T + device_id : FLASHWORD(0x2227), + block_size : 0x00040000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 8, + device_size: 0x00200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x00200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x1c0000 * CYGNUM_FLASH_INTERLEAVE, + 0x038000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29PL160-B + device_id : FLASHWORD(0x2245), + block_size : 0x00040000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 8, + device_size: 0x00200000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x00200000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x038000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV200 + { // AM29LV200-T + device_id : FLASHWORD(0x223b), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 4, + device_size: 0x40000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x40000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x030000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29LV200-B + device_id : FLASHWORD(0x22bf), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 4, + device_size: 0x40000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x40000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_ST_M29W200B + { // ST M29W200BT + device_id : FLASHWORD(0x0051), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 4, + device_size: 0x40000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x40000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x030000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // ST M29W200BB + device_id : FLASHWORD(0x0057), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 4, + device_size: 0x40000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x40000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_ST_M29W320D + { // M29W320DT + device_id : FLASHWORD(0x22ca), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, // offset + 0x008000 * CYGNUM_FLASH_INTERLEAVE, // size 1 + 0x002000 * CYGNUM_FLASH_INTERLEAVE, // size 2 + 0x002000 * CYGNUM_FLASH_INTERLEAVE, // size 3 + 0x004000 * CYGNUM_FLASH_INTERLEAVE, // size 4 + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // M29W320DB + device_id : FLASHWORD(0x22cb), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, // offset + 0x004000 * CYGNUM_FLASH_INTERLEAVE, // size 1 + 0x002000 * CYGNUM_FLASH_INTERLEAVE, // size 2 + 0x002000 * CYGNUM_FLASH_INTERLEAVE, // size 3 + 0x008000 * CYGNUM_FLASH_INTERLEAVE, // size 4 + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV320D + { // AM29LV320DT + device_id : FLASHWORD(0x22F6), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29LV320D + device_id : FLASHWORD(0x22F9), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL322D + { // AM29DL322D-T + device_id : FLASHWORD(0x2255), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x380000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, + { // AM29DL322D-B + device_id : FLASHWORD(0x2256), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x80000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL323D + { // AM29DL323D-T + device_id : FLASHWORD(0x2250), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x300000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, + { // AM29DL323D-B + device_id : FLASHWORD(0x2253), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x100000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL324D + { // AM29DL324D-T + device_id : FLASHWORD(0x225c), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x3f0000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x200000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, + { // AM29DL324D-B + device_id : FLASHWORD(0x225f), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x400000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x200000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29DL640D +{ // AM29DL640D + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2202), + device_id3 : FLASHWORD(0x2201), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x800000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x7F0000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x700000 * CYGNUM_FLASH_INTERLEAVE, + 0x400000 * CYGNUM_FLASH_INTERLEAVE, + 0x100000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV400 + { // AM29LV400-T + device_id : FLASHWORD(0x22b9), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 8, + device_size: 0x80000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x80000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0xf0000 * CYGNUM_FLASH_INTERLEAVE, + 0x08000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x04000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29LV400-B + device_id : FLASHWORD(0x22ba), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 8, + device_size: 0x80000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x80000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29F800 + { // AM29F800-T + device_id : FLASHWORD(0x22d6), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0xf0000 * CYGNUM_FLASH_INTERLEAVE, + 0x08000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x04000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29F800-B + device_id : FLASHWORD(0x2258), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV800 + { // AM29LV800-T + device_id : FLASHWORD(0x22da), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0xf0000 * CYGNUM_FLASH_INTERLEAVE, + 0x08000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x02000 * CYGNUM_FLASH_INTERLEAVE, + 0x04000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, + { // AM29LV800-B + device_id : FLASHWORD(0x225b), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV640 + { // MBM29LV640xx + device_id : FLASHWORD(0x22d7), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x800000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV640M + { // MBM29LV640xx + device_id : FLASHWORD(0x227e), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x800000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_TC58FVB800 + { // Toshiba TC58FVB800 (compatible with AM29LV800-B except for IDs.) + device_id : FLASHWORD(0xCE), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 16, + device_size: 0x100000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x100000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x004000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x002000 * CYGNUM_FLASH_INTERLEAVE, + 0x008000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : false, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29LV256 + { // AMD AM29LV256 + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2212), + device_id3 : FLASHWORD(0x2201), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 512, + device_size: 0x2000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x2000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 16, + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29PL032J + { // S29PL032J + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x220a), + device_id3 : FLASHWORD(0x2201), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 64, + device_size: 0x0400000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x4000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x3F0000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x0380000 * CYGNUM_FLASH_INTERLEAVE, + 0x0200000 * CYGNUM_FLASH_INTERLEAVE, + 0x0080000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29PL064J + { // S29PL064J + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2202), + device_id3 : FLASHWORD(0x2201), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x0800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x8000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x7F0000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x0700000 * CYGNUM_FLASH_INTERLEAVE, + 0x0400000 * CYGNUM_FLASH_INTERLEAVE, + 0x0100000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29PL127J + { // S29PL127J + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2220), + device_id3 : FLASHWORD(0x2200), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x000000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0xFF0000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x0e00000 * CYGNUM_FLASH_INTERLEAVE, + 0x0800000 * CYGNUM_FLASH_INTERLEAVE, + 0x0200000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL064M + { // AMD/SPANSION S29GL064M + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2210), + device_id3 : FLASHWORD(0x2201), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x0800000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x8000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : true, + bootblocks : { 0x00000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x7F0000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + 0x2000 * CYGNUM_FLASH_INTERLEAVE, + _LAST_BOOTBLOCK + }, + banked : true, + banks : { 0x0700000 * CYGNUM_FLASH_INTERLEAVE, + 0x0400000 * CYGNUM_FLASH_INTERLEAVE, + 0x0100000 * CYGNUM_FLASH_INTERLEAVE, + 0 + }, + bufsiz : 1 + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL128N + { // AMD/SPANSION S29GL128N + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2221), + device_id3 : FLASHWORD(0x2201), + block_size : 0x20000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 128, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 16, + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL256N + { // AMD/SPANSION S29GL256N + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2222), + device_id3 : FLASHWORD(0x2201), + block_size : 0x20000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x2000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x2000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 16, + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL512N + { // AMD/SPANSION S29GL512N + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2223), + device_id3 : FLASHWORD(0x2201), + block_size : 0x20000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 512, + device_size: 0x4000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x4000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 16, + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL128M + { // AMD/SPANSION S29GL128M + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2212), + device_id3 : FLASHWORD(0x2200), + block_size : 0x10000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 256, + device_size: 0x1000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x1000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 16, + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL512P + { // AMD/SPANSION S29GL512P + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2223), + device_id3 : FLASHWORD(0x2201), + block_size : 0x20000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 512, + device_size: 0x4000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x4000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 32, + }, +#endif +#ifdef CYGHWR_DEVS_FLASH_AMD_S29GL01GP + { // AMD/SPANSION S29GL01GP + long_device_id: true, + device_id : FLASHWORD(0x227e), + device_id2 : FLASHWORD(0x2228), + device_id3 : FLASHWORD(0x2201), + block_size : 0x20000 * CYGNUM_FLASH_INTERLEAVE, + block_count: 1024, + device_size: 0x8000000 * CYGNUM_FLASH_INTERLEAVE, + base_mask : ~(0x8000000 * CYGNUM_FLASH_INTERLEAVE - 1), + bootblock : false, + banked : false, + bufsiz : 32, + }, +#endif + +#endif // 16 bit devices + +#endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_PARTS_INL diff --git a/ecos/packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog new file mode 100644 index 0000000..f3d9a9d --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/ChangeLog @@ -0,0 +1,220 @@ +2009-04-20 Rene Schipp von Branitz Nielsen <rbn@vitesse.com> + + * src/am29xxxxx.c: Added set of parentheses around macro + parameters used in multiplications. Fixes 16as8 bug. + +2008-12-19 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/flash_am29xxxxx_v2.cdl: Doh, fix doc link properly. + +2008-11-20 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/flash_am29xxxxx_v2.cdl: Fix doc link. + +2008-09-24 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx_aux.c (am29_hw_program): fix handling of parallel + chips. Get the debug diagnostics to build cleanly. + +2008-05-13 Jonathan Larmour <jifl@eCosCentric.com> + + * src/am29xxxxx_aux.c (am29_hw_query): Allow devices to return + device IDs of larger than a byte. + +2007-07-08 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx.c, src/am29xxxxx_aux.c: add 2ram entry and exit + hooks to give HALs some extra control over the low-level flash + operations. + +2007-06-21 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx_aux.c: issue a memory barrier after every command + that gets sent to the flash, to avoid problems with pipelines that + mess about with write ordering. + +2007-05-31 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx.c: skip data cache manipulation on architectures + which do not have a data cache. + +2007-05-29 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/flash_am29xxxxx_v2.cdl + (CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_RESET_NEEDS_RESUME): New option. + Allow Flash devices to indicate that they should be sent a "resume" + command on startup. + * src/am29xxxxx_aux.c (am29_hw_force_all_suspended_resume): New + function to implement above CDL. + (cyg_am29xxxxx_init_check_dev): Call the new function. + (cyg_am29xxxxx_init_cfi): Ditto. + (am29_hw_cfi): manufacturer_id and vendor private areas need only + lowest byte taken, to handle multiple parallel devices. + +2007-03-29 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx_aux.c (am29_hw_erase): use DQ7 to detect + termination instead of DQ6. This avoids hardware problems where + the toggling of DQ6 is not detected. + +2007-03-05 Nick Garnett <nickg@ecoscentric.com> + + * src/am29xxxxx_aux.c (am29_hw_cfi): Added missing AM29_SWAP() to + fetch of offset of vendor specific data. + +2006-09-27 Nick Garnett <nickg@ecoscentric.com> + + * src/am29xxxxx_aux.c (am29_hw_cfi): Added generic code to deal + with flash parts that may specify their erase regions in reverse + order to reality. Removed older code that was too specific to + particular devices. + A few changes to the diagnostics in various places. + + * cdl/flash_am29xxxxx_v2.cdl: Replaced + CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_AT49_CFI with + CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CFI_BOGOSITY. This option + performs much the same purpose, but is generic to many more flash + parts. + +2006-08-31 Nick Garnett <nickg@ecoscentric.com> + + * src/am29xxxxx_aux.c: Added support for ST flash parts which have + similar, but not identical, peculiarities in their CFI data to the + Atmel parts supported earlier. + +2006-08-24 Jonathan Larmour <jifl@eCosCentric.com> + + * src/am29xxxxx.c: Provide a default HAL_MEMORY_BARRIER() + define if the HAL hasn't provided one. + * src/am29xxxxx_aux.c: Use HAL_MEMORY_BARRIER() any time the + flash is reset back to read array mode. Some processors + need to have their write buffers flushed. + +2006-06-29 Nick Garnett <nickg@ecoscentric.com> + + * cdl/flash_am29xxxxx_v2.cdl: + * src/am29xxxxx_aux.c: + Added configurable delay between each word during + programming. Some targets seem to need this. + Also added some simple diagnostics. + +2006-05-15 John Dallaway <jld@ecoscentric.com> + + * doc/am29xxxxx.sgml: Fix missing </refentry> tag. + * cdl/flash_am29xxxx_v2.cdl: Reference package documentation. + +2005-09-26 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx.c, src/am29xxxxx_aux.c: add AM29_SWAP() support for + platforms where the bus connection is wired up strangely. + + * src/am29xxxxx_aux.c, cdl/flash_am29xxxxx_v2.cdl: add optional + support for certain Atmel chips which have a peculiar + implementation of CFI. + +2005-08-17 Jonathan Larmour <jifl@eCosCentric.com> + + * cdl/flash_am29xxxx_v2.cdl: Provide new + CYGIMP_DEVS_FLASH_AMD_AM29XXXXX_V2_LEAVE_INTERRUPTS_ENABLED + and CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY options + to provide better control of when to enable/disable interrupts + or caches. Taken from the Strata flash example. + * include/am29xxxxx_dev.h: Declare cyg_at49xxxx_softlock, _hardlock + and _unlock variants. + * src/am29xxxxx.c: Define AT49 locking commands. + Provide AM29_UNCACHE_ADDRESS in line with the Strata driver, + to be controlled by the above new CDL options, in place of + AM29_P2V. + * src/am29xxxxx_aux.c: Provide AT49 lock status definition. + Provide AT49 softlock/hardlock/unlock API functions and + underlying implementation functions. + Adopt AM29_UNCACHED_ADDRESS rename. + * doc/am29xxxxx.sgml: Update documentation to cover AT49xxxx + locking operations and above new CDL options. + +2005-06-12 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx_aux.c (cyg_am29xxxxx_program): remove unnecessary + loops variable + * cdl/flash_am29xxxxx_v2.cdl: minor reorganization to put the + important config option first + * doc/am29xxxxx.sgml: document the important config options + +2005-02-23 Bart Veer <bartv@ecoscentric.com> + + * doc/am29xxxxx.sgml: bring up to date. + +2005-01-19 Jonathan Larmour <jifl@eCosCentric.com> + + * src/am29xxxxx_aux.c (am29_hw_erase): Handle interleaved + (parallel) flash correctly when one device finishes before another. + (am29_hw_program): Similar. + (cyg_am29xxxxx_program): Use assert correctly. + + * src/am29xxxxx.c (AM29_NEXT_DATUM_32): Use cyg_uint32, not + cyg_uint16. + +2004-12-02 Bart Veer <bartv@ecoscentric.com> + + * src/am29xxxxx.c, include/am29xxxxx_dev.h: <cyg/io/flash_priv.h> + no longer exists, use <cyg/io/flash_dev.h> instead. + +2004-11-29 Bart Veer <bartv@ecoscentric.com> + + * include/am29xxxxx_dev.h, src/am29xxxxx.c: eliminate + hwr_map_error() support, no longer needed + + * include/am29xxxxx_dev.h, src/am29xxxxx.c, src/am29xxxxx_aux.c: + The dummy init/query/lock/unlock functions have been moved to the + generic flash package. That also now exports an anonymizer + function. + +2004-11-25 Bart Veer <bartv@ecoscentric.com> + + * cdl/flash_am29xxxxx_v2.cdl, src/am29xxxxx.c, + src/am29xxxxx_aux.c: this driver can manage the flash and + interrupts itself, without support from the generic flash code. + +2004-11-22 Bart Veer <bartv@ecoscentric.com> + + * include/am29xxxxx_dev.h, src/am29xxxxx.c, src/am29xxxxx_aux.c, + doc/am29xxxxx.sgml: implement changes to the interface between the + generic flash code and the device drivers. + * include/am29xxxxx_dev.h: rename cyg_block_info to + cyg_flash_block_info + +2004-11-21 Bart Veer <bartv@ecoscentric.com> + + * doc/am29xxxxx.sgml: describe CDL implications for custom locking + functions and additional devices. + + * cdl/flash_am29xxxxx_v2.cdl: CYGHWR_IO_FLASH_DEVICE_V2 is now + implicit + +2004-11-05 Bart Veer <bartv@ecoscentric.com> + + * New AM29xxxxx flash driver created + +//=========================================================================== +// ####GPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +// +// 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 or (at your option) any +// later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., 51 Franklin Street, +// Fifth Floor, Boston, MA 02110-1301, USA. +// ------------------------------------------- +// ####GPLCOPYRIGHTEND#### +//=========================================================================== diff --git a/ecos/packages/devs/flash/amd/am29xxxxxv2/current/cdl/flash_am29xxxxx_v2.cdl b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/cdl/flash_am29xxxxx_v2.cdl new file mode 100644 index 0000000..f59b383 --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/cdl/flash_am29xxxxx_v2.cdl @@ -0,0 +1,222 @@ +# ==================================================================== +# +# flash_am29xxxxx_v2.cdl +# +# Device driver for AMD am29xxxxx flash chips and compatibles +# +# ==================================================================== +## ####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +## +## eCos 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 or (at your option) any later +## version. +## +## eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +## +## As a special exception, if other files instantiate templates or use +## macros or inline functions from this file, or you compile this file +## and link it with other works to produce a work based on this file, +## this file does not by itself cause the resulting work to be covered by +## the GNU General Public License. However the source code for this file +## must still be made available in accordance with section (3) of the GNU +## General Public License v2. +## +## This exception does not invalidate any other reasons why a work based +## on this file might be covered by the GNU General Public License. +## ------------------------------------------- +## ####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: +# Date: 2004-11-05 +# +#####DESCRIPTIONEND#### +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 { + display "AMD am29xxxxx flash memory support" + doc ref/devs-flash-am29xxxxx.html + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + implements CYGHWR_IO_FLASH_DEVICE + include_dir cyg/io + compile am29xxxxx.c + + description " + Flash memory support for AMD AM29xxxxx devices and compatibles. + This driver implements the V2 flash driver API" + + cdl_option CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_TIMEOUT { + display "Maximum number of iterations during a write" + flavor data + default_value 100000000 + legal_values 1024 to 0x7fffffff + description " + Flash program operations may take a long time, and the driver + needs to poll the device to detect when the operation has + completed. This option controls the maximum number of iterations + of the polling loop, before the driver will give up. The timeout + should never actually trigger, as long as the hardware is + functioning correctly. If a timeout does occur the flash device + may be left in an inconsistent state. If very slow flash devices + are used then the platform HAL may require a larger timeout." + } + + cdl_option CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_DELAY { + display "Delay between words while programming" + flavor data + default_value 0 + legal_values 0 to 0x7fffffff + description "The timings of certain processors and flash devices mean that + a short delay may be required between each word as it is programmed. + This option defines that delay in terms of iterations of a delay + loop." + } + + cdl_option CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_TIMEOUT { + display "Maximum number of iterations during a block erase" + flavor data + default_value 100000000 + legal_values 1024 to 0x7fffffff + description " + The driver needs to poll the flash device during a block erase + to detect when the operation has completed. This option controls + the maximum number of iterations of the polling loop, before the + driver will give up. The timeout should never actually trigger, + as long as the hardware is functioning correctly. If a timeout + does occur the flash device may be left in an inconsistent state. + If very slow flash devices are used then the platform HAL may + require a larger timeout." + } + + cdl_option CYGIMP_DEVS_FLASH_AMD_AM29XXXXX_V2_LEAVE_INTERRUPTS_ENABLED { + display "Leave interrupts enabled during flash operations" + active_if { ! CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY } + default_value 0 + description " + On typical hardware erasing or programming a flash block requires + disabling interrupts and possibly the cache. During these operations + some or all of the flash hardware will be unusable, and disabling + interrupts is the only reliable way of ensuring that no interrupt + handler or other thread will try to access the flash in the middle + of the operation. This can have a major impact on the real-time + responsiveness of typical applications. + + In some circumstances it is possible to leave interrupts enabled. + The application must run in RAM, not in flash. There must be some + way of accessing the flash which bypasses the cache. The application + must only access the flash using the proper API, for example + cyg_flash_read(), which ensures that only one thread at a time can + access a flash device. Finally there must be no possibility of + entering a ROM monitor running in flash. This can happen if RedBoot + is used as the ROM monitor and virtual vectors are enabled. It can + also happen when debugging the application via RedBoot or gdb stubs. + + If the application can absolutely guarantee that the flash will not be + accessed during a flash operation then it is possible to enable this option, + improving interrupt latency. Any unexpected flash accesses are likely + to cause a system crash. If in doubt leave this option disabled." + } + + cdl_interface CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY { + display "Flash memory accesses are always cached" + flavor bool + description " + Flash memory devices are usually accessed via the cache to achieve + acceptable performance. However erase and program operations need + to access the flash directly, bypassing the cache. On some targets + it is possible to access the flash in an uncached part of the + address space, for example by suitable MMU settings. On other + targets it is necessary to disable the cache while erasing or + programming blocks of flash. In the latter case the platform HAL + will implement this interface." + } + + cdl_interface CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CFI_BOGOSITY { + display "Include support for unusual CFI implementation" + flavor bool + description " + CFI, Common Flash Interface, is a standard allowing device drivers + to query the hardware for characteristics such as the erase region + layout. Some flash chips have a somewhat strange implementation of CFI, + requiring extra code within the device driver. If CFI is used for device + initialization and if the platform may come with one of these flash chips + then the platform HAL will implement this interface." + } + + cdl_interface CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_RESET_NEEDS_RESUME { + display "Erase/program resume is needed after reset" + flavor bool + description " + With true AMD-compatible flash parts, a reset command will also + abort any suspended erase or program operations. But on some + parts which are nearly but not quite compatible, such as AT49xxxxx, + this does not happen, and so an erase/program resume command is + needed after a soft reset in order to be able to use the chip." + } + + cdl_option CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_REGIONS { + display "Number of different erase regions" + flavor data + default_value 4 + legal_values 1 to 64 + description " + Flash devices vary widely in the way the various flash blocks are + laid out. In uniform devices all flash blocks are the same size, + for example 64 blocks of 64K each. Other devices have a boot block, + where one of the big blocks is subdivided into a number of smaller + ones. For example there could be a 16K block, followed by two 8K blocks, + then a 32K block, and finally 63 64K blocks. Each sequence of blocks + of a given size is known as an erase region, so a uniform device has + a single erase region and the above boot block device has four + erase regions. The driver needs to know the maximum number of erase + regions that may be present, especially if CFI is used to determine + the block details at run-time. Typically this option is controlled + by a requires property in the platform HAL, so users do not need + to edit it." + } + + cdl_component CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2_OPTIONS { + display "AMD AM29xxxxx driver build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building the AMD am29xxxxx + flash driver, and details of which tests are built." + + cdl_option CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the AMD am29xxxxx flash driver. These flags + are used in addition to the set of global flags." + } + + cdl_option CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the AMD am29xxxxx flash driver. These flags + are removed from the set of global flags if present." + } + } +} diff --git a/ecos/packages/devs/flash/amd/am29xxxxxv2/current/doc/am29xxxxx.sgml b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/doc/am29xxxxx.sgml new file mode 100644 index 0000000..cbe7e29 --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/doc/am29xxxxx.sgml @@ -0,0 +1,789 @@ +<!-- DOCTYPE part PUBLIC "-//OASIS//DTD DocBook V3.1//EN" --> + +<!-- {{{ Banner --> + +<!-- =============================================================== --> +<!-- --> +<!-- am29xxxxx.sgml --> +<!-- --> +<!-- Documentation for the am29xxxxx flash device driver. --> +<!-- --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTBEGIN#### --> +<!-- =============================================================== --> +<!-- Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. --> +<!-- This material may be distributed only subject to the terms --> +<!-- and conditions set forth in the Open Publication License, v1.0 --> +<!-- or later (the latest version is presently available at --> +<!-- http://www.opencontent.org/openpub/) --> +<!-- Distribution of the work or derivative of the work in any --> +<!-- standard (paper) book form is prohibited unless prior --> +<!-- permission obtained from the copyright holder --> +<!-- =============================================================== --> +<!-- ####ECOSDOCCOPYRIGHTEND#### --> +<!-- =============================================================== --> +<!-- #####DESCRIPTIONBEGIN#### --> +<!-- --> +<!-- Author(s): bartv --> +<!-- Date: 2004/11/05 --> +<!-- --> +<!-- ####DESCRIPTIONEND#### --> +<!-- =============================================================== --> + +<!-- }}} --> + +<part id="devs-flash-am29xxxxx"><title>AMD AM29xxxxx Flash Device Driver</title> + +<refentry id="am29xxxxx"> + <refmeta> + <refentrytitle>Overview</refentrytitle> + </refmeta> + <refnamediv> + <refname>Overview</refname> + <refpurpose>eCos Support for AMD AM29xxxxx Flash Devices and Compatibles</refpurpose> + </refnamediv> + + <refsect1 id="am29xxxxx-description"><title>Description</title> + <para> +The <varname>CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2</varname> AMD +AM29xxxxx V2 flash driver package implements support for the AM29xxxxx +family of flash devices and compatibles. Normally the driver is not +accessed directly. Instead application code will use the API provided +by the generic flash driver package +<varname>CYGPKG_IO_FLASH</varname>, for example by calling functions +like <function>cyg_flash_program</function>. + </para> + <para> +The driver imposes one restriction on application code which +developers should be aware of: when programming the flash the +destination addresses must be aligned to a bus boundary. For example +if the target hardware has a single flash device attached to a 16-bit +bus then program operations must involve a multiple of 16-bit values +aligned to a 16-bit boundary. Note that it is the bus width that +matters, not the device width. If the target hardware has two 16-bit +devices attached to a 32-bit bus then program operations must still be +aligned to a 32-bit boundary, even though in theory a 16-bit boundary +would suffice. In practice this is rarely an issue, and requiring the +larger boundary greatly simplifies the code and improves performance. + </para> + <note><para> +Many eCos targets with AM29xxxxx or compatible flash devices will +still use the older driver package +<varname>CYGPKG_DEVS_FLASH_AMD_AM29XXXXX</varname>. Only newer ports +and some older ports that have been converted will use the V2 driver. +This documentation only applies to the V2 driver. + </para></note> + </refsect1> + + <refsect1 id="am29xxxxx-config"><title>Configuration Options</title> + <para> +The AM29xxxxx flash driver package will be loaded automatically when +configuring eCos for a target with suitable hardware. However the +driver will be inactive unless the generic flash package +<varname>CYGPKG_IO_FLASH</varname> is loaded. It may be necessary to +add this generic package to the configuration explicitly before the +driver functionality becomes available. There should never be any need +to load or unload the AM29xxxx driver package. + </para> + <para> +There are a number of configuration options, relating mostly to hardware +characteristics. It is very rare that application developers need to +change any of these. For example the option +<varname>CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_REGIONS</varname> +may need a non-default value if the flash devices used on the target +have an unusual boot block layout. If so the platform HAL will impose +a requires constraint on this option and the configuration system will +resolve the constraint. The only time it might be necessary to change +the value manually is if the actual board being used is a variant of +the one supported by the platform HAL and uses a different flash chip. + </para> + </refsect1> +</refentry> + +<refentry id="am29xxxxx-instance"> + <refmeta> + <refentrytitle>Instantiating an AM29xxxxx Device</refentrytitle> + </refmeta> + <refnamediv> + <refname>Instantiating</refname> + <refpurpose>including the driver in an eCos target</refpurpose> + </refnamediv> + <refsynopsisdiv> + <funcsynopsis> + <funcsynopsisinfo> +#include <cyg/io/am29xxxxx_dev.h> + </funcsynopsisinfo> + <funcprototype> + <funcdef>int <function>cyg_am29xxxxx_init_check_devid_XX</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef>int <function>cyg_am29xxxxx_init_cfi_XX</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef>int <function>cyg_am29xxxxx_erase_XX</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + <paramdef>cyg_flashaddr_t <parameter>addr</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef>int <function>cyg_am29xxxxx_program_XX</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + <paramdef>cyg_flashaddr_t <parameter>addr</parameter></paramdef> + <paramdef>const void* <parameter>data</parameter></paramdef> + <paramdef>size_t <parameter>len</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef>int <function>cyg_at49xxxx_softlock</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + <paramdef>const cyg_flashaddr_t <parameter>addr</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef>int <function>cyg_at49xxxx_hardlock</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + <paramdef>const cyg_flashaddr_t <parameter>addr</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef>int <function>cyg_at49xxxx_unlock</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + <paramdef>const cyg_flashaddr_t <parameter>addr</parameter></paramdef> + </funcprototype> + <funcprototype> + <funcdef>int <function>cyg_am29xxxxx_read_devid_XX</function></funcdef> + <paramdef>struct cyg_flash_dev* <parameter>device</parameter></paramdef> + </funcprototype> + </funcsynopsis> + </refsynopsisdiv> + + <refsect1 id="am29xxxxx-instance-description"><title>Description</title> + <para> +The AM29xxxxx family contains some hundreds of different flash +devices, all supporting the same basic set of operations but with +various common or uncommon extensions. The devices vary in capacity, +performance, boot block layout, and width. There are also +platform-specific issues such as how many devices are actually present +on the board and where they are mapped in the address space. The +AM29xxxxx driver package cannot know the details of every chip and +every platform. Instead it is the responsibility of another package, +usually the platform HAL, to supply the necessary information by +instantiating some data structures. Two pieces of information are +especially important: the bus configuration and the boot block layout. + </para> + <para> +Flash devices are typically 8-bits, 16-bits, or 32-bits wide (64-bit +devices are not yet in common use). Most 16-bit devices will also +support 8-bit accesses, but not all. Similarly 32-bit devices can be +accessed 16-bits at a time or 8-bits at a time. A board will have one +or more of these devices on the bus. For example there may be a single +16-bit device on a 16-bit bus, or two 16-bit devices on a 32-bit bus. +The processor's bus logic determines which combinations are possible, +and there will be a trade off between cost and performance: two 16-bit +devices in parallel can provide twice the memory bandwidth of a single +device. The driver supports the following combinations: + </para> + <variablelist> + <varlistentry> + <term>8</term> + <listitem><para> +A single 8-bit flash device on an 8-bit bus. + </para></listitem> + </varlistentry> + <varlistentry> + <term>16</term> + <listitem><para> +A single 16-bit flash device on a 16-bit bus. + </para></listitem> + </varlistentry> + <varlistentry> + <term>32</term> + <listitem><para> +A single 32-bit flash device on an 32-bit bus. + </para></listitem> + </varlistentry> + <varlistentry> + <term>88</term> + <listitem><para> +Two parallel 8-bit devices on an 16-bit bus. + </para></listitem> + </varlistentry> + <varlistentry> + <term>8888</term> + <listitem><para> +Four parallel 8-bit devices on a 32-bit bus. + </para></listitem> + </varlistentry> + <varlistentry> + <term>1616</term> + <listitem><para> +Two parallel 16-bit devices on a 32-bit bus, with one device providing +the bottom two bytes of each 32-bit datum and the other device +providing the top two bytes. + </para></listitem> + </varlistentry> + <varlistentry> + <term>16as8</term> + <listitem><para> +A single 16-bit flash device connected to an 8-bit bus. + </para></listitem> + </varlistentry> + </variablelist> + <para> +These configuration all require slightly different code to manipulate +the hardware. The AM29xxxxx driver package provides separate functions +for each configuration, for example +<function>cyg_am29xxxxx_erase_16</function> and +<function>cyg_am29xxxxx_program_1616</function>. + </para> + <caution><para> +At the time of writing not all the configurations have been tested. + </para></caution> + <para> +The second piece of information is the boot block layout. Flash +devices are subdivided into blocks (also known as sectors - both terms +are in common use). Some operations such as erase work on a whole +block at a time, and for most applications a block is the smallest +unit that gets updated. A typical block size is 64K. It is inefficient +to use an entire 64K block for small bits of configuration data and +similar information, so many flash devices also support a number of +smaller boot blocks. A typical 2MB flash device could have a single +16K block, followed by two 8K blocks, then a 32K block, and finally 31 +full-size 64K blocks. The boot blocks may appear at the bottom or the +top of the device. So-called uniform devices do not have boot blocks, +just full-size ones. The driver needs to know the boot block layout. +With modern devices it can work this out at run-time, but often it is +better to provide the information statically. + </para> + </refsect1> + + <refsect1 id="am29xxxxx-instance-example"><title>Example</title> + <para> +In most cases flash support is specific to a platform. Even if two +platforms happen to use the same flash device there are likely to be +differences such as the location in the address map. Hence there is +little possibility of re-using the platform-specific code, and this +code should be placed in the platform HAL rather than in a separate +package. Typically this involves a separate file and a corresponding +compile property in the platform HAL's CDL: + </para> + <programlisting width=72> +cdl_package CYGPKG_HAL_M68K_ALAIA { + … + compile -library=libextras.a alaia_flash.c + … +} + </programlisting> + <para> +The contents of this file will not be accessed directly, only +indirectly via the generic flash API, so normally it would be removed +by link-time garbage collection. To avoid this the object file has to +go into <filename>libextras.a</filename>. + </para> + <para> +The actual file <filename>alaia_flash.c</filename> will look something like: + </para> + <programlisting> +#include <pkgconf/system.h> +#ifdef CYGPKG_DEVS_FLASH_AMD_AM29XXXXX_V2 + +#include <cyg/io/flash.h> +#include <cyg/io/flash_dev.h> +#include <cyg/io/am29xxxxx_dev.h> + +static const CYG_FLASH_FUNS(hal_alaia_flash_amd_funs, + &cyg_am29xxxxx_init_check_devid_16, + &cyg_flash_devfn_query_nop, + &cyg_am29xxxxx_erase_16, + &cyg_am29xxxxx_program_16, + (int (*)(struct cyg_flash_dev*, const cyg_flashaddr_t, void*, size_t))0, + &cyg_flash_devfn_lock_nop, + &cyg_flash_devfn_unlock_nop); + +static const cyg_am29xxxxx_dev hal_alaia_flash_priv = { + .devid = 0x45, + .block_info = { + { 0x00004000, 1 }, + { 0x00002000, 2 }, + { 0x00008000, 1 }, + { 0x00010000, 63 } + } +}; + +CYG_FLASH_DRIVER(hal_alaia_flash, + &hal_alaia_flash_amd_funs, + 0, + 0xFFC00000, + 0xFFFFFFFF, + 4, + hal_alaia_flash_priv.block_info, + &hal_alaia_flash_priv +); +#endif + </programlisting> + <para> +The bulk of the file is protected by an <literal>#ifdef</literal> for +the AM29xxxxx flash driver. That driver will only be active if the +generic flash support is enabled. Without that support there will be +no way of accessing the device so instantiating the data structures +would serve no purpose. The rest of the file is split into three +structure definitions. The first supplies the functions which will be +used to perform the actual flash accesses, using a macro provided by +the generic flash code in <filename +class="headerfile">cyg/io/flash_dev.h</filename>. The relevant ones +have an <literal>_16</literal> suffix, indicating that on this board +there is a single 16-bit flash device on a 16-bit bus. The second +provides information specific to AM29xxxxx flash devices. +The third provides the <structname>cyg_flash_dev</structname> +structure needed by the generic flash code, which contains pointers to +the previous two. + </para> + </refsect1> + + <refsect1 id="am29xxxxx-instance-functions"><title>Functions</title> + <para> +All eCos flash device drivers must implement a standard interface, +defined by the generic flash code <varname>CYGPKG_IO_FLASH</varname>. +This interface includes a table of seven function pointers for various +operations: initialization, query, erase, program, read, locking and +unlocking. The query operation is optional and the generic flash +support provides a dummy implementation +<function>cyg_flash_devfn_query_nop</function>. AM29xxxxx flash +devices are always directly accessible so there is no need for a +separate read function. The remaining functions are more complicated. + </para> + <para> +Usually the table can be declared <literal>const</literal>. In a ROM +startup application this avoids both ROM and RAM copies of the table, +saving a small amount of memory. <literal>const</literal> should not +be used if the table may be modified by a platform-specific +initialization routine. + </para> + + <refsect2 id="am29xxxxx-instance-functions-init"><title>Initialization</title> + <para> +There is a choice of three main initialization functions. The simplest +is <function>cyg_flash_devfn_init_nop</function>, which does nothing. +It can be used if the <structname>cyg_am29xxxxx_dev</structname> and +<structname>cyg_flash_dev</structname> structures are fully +initialized statically and the flash will just work without special +effort. This is useful if it is guaranteed that the board will always +be manufactured using the same flash chip, since the nop function +involves the smallest code size and run-time overheads. + </para> + <para> +The next step up is +<function>cyg_am29xxxxx_init_check_devid_XX</function>, where +<literal>XX</literal> will be replaced by the suffix appropriate for +the bus configuration. It is still necessary to provide all the device +information statically, including the <structfield>devid</structfield> +field in the <structname>cyg_am29xxxxx_dev</structname> structure. +This initialization function will attempt to query the flash device +and check that the provided device id matches the actual hardware. If +there is a mismatch the device will be marked uninitialized and +subsequent attempts to manipulate the flash will fail. + </para> + <para> +If the board may end up being manufactured with any of a number of +different flash chips then the driver can perform run-time +initialization, using a <function>cyg_am29xxxxx_init_cfi_XX</function> +function. This queries the flash device as per the Common Flash Memory +Interface Specification, supported by all current devices (although +not necessarily by older devices). The +<structfield>block_info</structfield> field in the +<structname>cyg_am29xxxxx_dev</structname> structure and the +<structfield>end</structfield> and +<structfield>num_block_infos</structfield> fields in the +<structname>cyg_flash_dev</structname> structure will be filled in. +It is still necessary to supply the <structfield>start</structfield> +field statically since otherwise the driver will not know how to +access the flash device. The main disadvantage of using CFI is that it +increases the code size. + </para> + <caution><para> +If CFI is used then the <structname>cyg_am29xxxxx_dev</structname> +structure must not be declared <literal>const</literal>. The CFI code +will attempt to update the structure and will fail if the structure is +held in read-only memory. This would leave the flash driver +non-functional. + </para></caution> + <para> +A final option is to use a platform-specific initialization function. +This may be useful if the board may be manufactured with one of a +small number of different flash devices and the platform HAL needs to +adapt to this. The AM29xxxxx driver provides a utility function to +read the device id, <function>cyg_am29xxxxx_read_devid_XX</function>: + </para> + <programlisting width=72> +static int +alaia_flash_init(struct cyg_flash_dev* dev) +{ + int devid = cyg_am29xxxxx_read_devid_1616(dev); + switch(devid) { + case 0x0042 : + … + case 0x0084 : + … + default: + return CYG_FLASH_ERR_DRV_WRONG_PART; + } +} + </programlisting> + <para> +There are many other possible uses for a platform-specific +initialization function. For example initial prototype boards might +have only supported 8-bit access to a 16-bit flash device rather than +16-bit access, but this problem was fixed in the next revision. The +platform-specific initialization function can figure out which model +board it is running on and replace the default +<literal>16as8</literal> functions with faster <literal>16</literal> +ones. + </para> + </refsect2> + + <refsect2 id="am29xxxxx-instance-functions-erase-program"><title>Erase and Program</title> + <para> +The AM29xxxxx driver provides erase and program functions appropriate +for the various bus configurations. On most targets these can be used +directly. On some targets it may be necessary to do some extra work +before and after the erase and program operations. For example if the +hardware has an MMU then the part of the address map containing the +flash may have been set to read-only, in an attempt to catch spurious +memory accesses. Erasing or programming the flash requires +write-access, so the MMU settings have to be changed temporarily. As +another example some flash device may require a higher voltage to be +applied during an erase or program operation. or a higher voltage may +be desirable to make the operation proceed faster. A typical +platform-specific erase function would look like this: + </para> + <programlisting width=72> +static int +alaia_flash_erase(struct cyg_flash_dev* dev, cyg_flashaddr_t addr) +{ + int result; + … // Set up the hardware for an erase + result = cyg_am29xxxxx_erase_32(dev, addr); + … // Revert the hardware change + return result; +} + </programlisting> + <para> +There are two configurations which affect the erase and program +functions, and which a platform HAL may wish to change: +<varname>CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_TIMEOUT</varname> +and +<varname>CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_TIMEOUT</varname>. +The erase and program operations both involve polling for completion, +and these timeout impose an upper bound on the polling loop. Normally +these operations should never take anywhere close to the timeout +period, so a timeout indicates a catastrophic failure that should +really be handled by a watchdog reset. A reset is particularly +appropriate because there will be no clean way of aborting the flash +operation. The main reason for the timeouts is to help with debugging +when porting to new hardware. If there is a valid reason why a +particular platform needs different timeouts then the platform HAL's +CDL can require appropriate values for these options. + </para> + </refsect2> + + <refsect2 id="am29xxxxx-instance-functions-locking"><title>Locking</title> + <para> +There is no single way of implementing the block lock and unlock +operations on all AM29xxxxx devices. If these operations are supported at +all then usually they involve manipulating the voltages on certain +pins. This would not be able to be handled by generic driver code since it requires +knowing how these pins can be manipulated via the processor's GPIO +lines. Therefore the AM29xxxxx driver does not usually provide lock and unlock +functions, and instead the generic dummy functions +<function>cyg_flash_devfn_lock_nop</function> and +<function>cyg_flash_devfn_unlock_nop</function> should be used. An <link +linkend="am29xxxxx-at49xxxx-locking">exception</link> exists for +the AT49xxxx family of devices which are sufficiently AMD +compatible in other respects. Otherwise, if a +platform does provide a way of implementing the locking then this can +be handled by platform-specific functions. + </para> + <programlisting width=72> +static int +alaia_lock(struct cyg_flash_dev* dev, const cyg_flashaddr_t addr) +{ + … +} + +static int +alaia_unlock(struct cyg_flash_dev* dev, const cyg_flashaddr_t addr) +{ + … +} + </programlisting> + <para> +If real locking functions are implemented then the platform HAL's CDL +script should implement the CDL interface +<varname>CYGHWR_IO_FLASH_BLOCK_LOCKING</varname>. Otherwise the +generic flash package may believe that none of the flash drivers in the +system provide locking functionality and disable the interface functions. + </para> + <refsect3 id="am29xxxxx-at49xxxx-locking"> + <title>AT49xxxx locking</title> + <para> +As locking is standardised across the AT49xxxx family of AMD AM29xxxxx +compatible Flash parts, a method supporting this is included within this +driver. <function>cyg_at49xxxx_softlock_XX</function> provides a means of +locking a Flash sector such that it may be subsequently unlocked. +<function>cyg_at49xxxx_hardlock_XX</function> locks a sector such that +it cannot be unlocked until after reset or a power cycle. +<function>cyg_at49xxxx_unlock_XX</function> unlocks a sector that has +previously been softlocked. At power on or Flash device reset, all sectors +default to being softlocked. + </para> + </refsect3> + </refsect2> + + <refsect2 id="am29xxxxx-instance-functions-other"><title>Other</title> + <para> +The driver provides a set of functions +<function>cyg_am29xxxxx_read_devid_XX</function>, one per supported +bus configuration. These functions take a single argument, a pointer +to the <structname>cyg_flash_dev</structname> structure, and return +the chip's device id. For older devices this id is a single byte. For +more recent devices the id is a 3-byte value, 0x7E followed by a +further two bytes that actually identify the device. +<function>cyg_am29xxxxx_read_devid_XX</function> is usually called +only from inside a platform-specific driver initialization routine, +allowing the platform HAL to adapt to the actual device present on the +board. + </para> + </refsect2> + </refsect1> + + <refsect1 id="am29xxxxx-instance-devpriv"><title>Device-Specific Structure</title> + <para> +The <structname>cyg_am29xxxxx_dev</structname> structure provides +information specific to AM29xxxxx flash devices, as opposed to the +more generic flash information which goes into the +<structname>cyg_flash_dev</structname> structure. There are only two +fields: <structfield>devid</structfield> and +<structfield>block_info</structfield>. + </para> + <para> +<structfield>devid</structfield> is only needed if the driver's +initialization function is set to +<function>cyg_am29xxxxx_init_check_devid_XX</function>. That function +will extract the actual device info from the flash chip and compare it +with the <structfield>devid</structfield> field. If there is a +mismatch then subsequent operations on the device will fail. + </para> + <para> +The <structfield>block_info</structfield> field consists of one or +more pairs of the block size in bytes and the number of blocks of that +size. The order must match the actual hardware device since the flash +code will use the table to determine the start and end locations of +each block. The table can be initialized in one of three ways: + </para> + <orderedlist> + <listitem><para> +If the driver initialization function is set to +<function>cyg_flash_devfn_init_nop</function> or +<function>cyg_am29xxxxx_init_check_devid_XX</function> then the block +information should be provided statically. This is appropriate if the +board will also be manufactured using the same flash chip. + </para></listitem> + <listitem><para> +If <function>cyg_am29xxxxx_init_cfi_XX</function> is used then this +will fill in the block info table. Hence there is no need for static +initialization. + </para></listitem> + <listitem><para> +If a platform-specific initialization function is used then either +this should fill in the block info table, or the info should be +provided statically. + </para></listitem> + </orderedlist> + <para> +The size of the <structfield>block_info</structfield> table is +determined by the configuration option +<varname>CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_REGIONS</varname>. +This has a default value of 4, which should suffice for nearly all +AM29xxxxx flash devices. If more entries are needed then the platform +HAL's CDL script should require a larger value. + </para> + <para> +If the <structname>cyg_am29xxxxx_dev</structname> structure is +statically initialized then it can be <literal>const</literal>. This +saves a small amount of memory in ROM startup applications. If the +structure is updated at run-time, either by +<function>cyg_am29xxxxx_init_cfi_XX</function> or by a +platform-specific initialization routine, then it cannot be +<literal>const</literal>. + </para> + </refsect1> + + <refsect1 id="am29xxxxx-instance-flash"><title>Flash Structure</title> + <para> +Internally the generic flash code works in terms of +<structname>cyg_flash_dev</structname> structures, and the platform +HAL should define one of these. The structure should be placed in the +<literal>cyg_flashdev</literal> table. The following fields need to be +provided: + </para> + <variablelist> + <varlistentry> + <term><structfield>funs</structfield></term> + <listitem><para> +This should point at the table of functions. + </para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>start</structfield></term> + <listitem><para> +The base address of the flash in the address map. On +some board the flash may be mapped into memory several times, for +example it may appear in both cached and uncached parts of the address +space. The <structfield>start</structfield> field should correspond to +the cached address. + </para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>end</structfield></term> + <listitem><para> +The address of the last byte in the flash. It can +either be statically initialized, or +<function>cyg_am29xxxxx_init_cfi_XX</function> will calculate +its value at run-time. + </para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>num_block_infos</structfield></term> + <listitem><para> +This should be the number of entries in the +<structfield>block_info</structfield> table. It can either be +statically initialized or it will be filled in by +<function>cyg_am29xxxxx_init_cfi_XX</function>. + </para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>block_info</structfield></term> + <listitem><para> +The table with the block information is held in the +<structname>cyg_am29xxxxx_dev</structname> structure, so this field +should just point into that structure. + </para></listitem> + </varlistentry> + <varlistentry> + <term><structfield>priv</structfield></term> + <listitem><para> +This field is reserved for use by the device driver. For the AM29xxxxx +driver it should point at the appropriate +<structname>cyg_am29xxxxx_dev</structname> structure. + </para></listitem> + </varlistentry> + </variablelist> + <para> +The <structname>cyg_flash_dev</structname> structure contains a number +of other fields which are manipulated only by the generic flash code. +Some of these fields will be updated at run-time so the structure +cannot be declared <literal>const</literal>. + </para> + </refsect1> + + <refsect1 id="am29xxxxx-instance-serial"><title>Multiple Devices</title> + <para> +A board may have several flash devices in parallel, for example two +16-bit devices on a 32-bit bus. It may also have several such banks +to increase the total amount of flash. If each device provides 2MB, +there could be one bank of 2 parallel flash devices at 0xFF800000 and +another bank at 0xFFC00000, giving a total of 8MB. This setup can be +described in several ways. One approach is to define two +<structname>cyg_flash_dev</structname> structures. The table of +function pointers can usually be shared, as can the +<structname>cyg_am29xxxxx_dev</structname> structure. Another approach +is to define a single <structname>cyg_flash_dev</structname> +structure but with a larger <structfield>block_info</structfield> +table, covering the blocks in both banks of devices. The second +approach makes more efficient use of memory. + </para> + <para> +Many variations are possible, for example a small slow flash device +may be used for initial bootstrap and holding the configuration data, +while there is also a much larger and faster device to hold a file +system. Such variations are usually best described by separate +<structname>cyg_flash_dev</structname> structures. + </para> + <para> +If more than one <structname>cyg_flash_dev</structname> structure is +instantiated then the platform HAL's CDL script should implement the +CDL interface <varname>CYGHWR_IO_FLASH_DEVICE</varname> once for every +device past the first. Otherwise the generic code may default to the +case of a single flash device and optimize for that. + </para> + </refsect1> + + <refsect1 id="am29xxxxx-instance-platform"><title>Platform-Specific Macros</title> + <para> +The AM29xxxxx driver source code includes the header files +<filename class="headerfile">cyg/hal/hal_arch.h</filename> and +<filename class="headerfile">cyg/hal/hal_io.h</filename>, and hence +indirectly the corresponding platform header files (if defined). +Optionally these headers can define macros which are used inside the +driver, thus giving the HAL limited control over how the driver works. + </para> + </refsect1> + + <refsect1 id="am29xxxxx-instance-cache"><title>Cache Management</title> + <para> +By default the AM29xxxxx driver assumes that the flash can be accessed +uncached, and it will use the HAL +<function>CYGARC_UNCACHED_ADDRESS</function> macro to map the cached +address in the <structfield>start</structfield> field of the +<structname>cyg_flash_dev</structname> structure into an uncached +address. If for any reason this HAL macro is inappropriate for the +flash then an alternative macro +<function>HAL_AM29XXXXX_UNCACHED_ADDRESS</function> can be defined +instead. However fixing the +<function>CYGARC_UNCACHED_ADDRESS</function> macro is normally the +better solution. + </para> + <para> +If there is no way of bypassing the cache then the platform HAL should +implement the CDL interface +<varname>CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY</varname>. The flash +driver will now disable and re-enable the cache as required. For +example a program operation will involve the following: + </para> + <programlisting width=72> + AM29_INTSCACHE_STATE; + AM29_INTSCACHE_BEGIN(); + while ( ! finished ) { + program data + } + AM29_INTSCACHE_END(); + </programlisting> + <para> +The default implementations of these INTSCACHE macros are as follows: +<varname>STATE</varname> defines any local variables that may be +needed, e.g. to save the current interrupt state; +<function>BEGIN</function> disables interrupts, synchronizes the data +caches, disables it, and invalidates the current contents; +<function>END</function> re-enables the cache and then +interrupts. The cache is only disabled when interrupts are disabled, +so there is no possibility of an interrupt handler running or a +context switch occurring while the cache is disabled, potentially +leaving the system running very slowly. The data cache synchronization +ensures that there are no dirty cache lines, so when the cache is +disabled the low-level flash write code will not see stale data in +memory. The invalidate ensures that at the end of the operation +higher-level code will not pick up stale cache contents instead of the +newly written flash data. + </para> + <para> +Some implementations of the HAL cache macros may not provide the exact +semantics required by the flash driver. For example +<function>HAL_DCACHE_DISABLE</function> may have an unwanted side +effect, or it may do more work than is needed here. The driver will +check for alternative macros +<function>HAL_AM29XXXXX_INTSCACHE_STATE</function>, +<function>HAL_AM29XXXXX_INTSCACHE_BEGIN</function> and +<function>HAL_AM29XXXXX_INTSCACHE_END</function>, using these instead of +the defaults. + </para> + </refsect1> + </refentry> +</part> diff --git a/ecos/packages/devs/flash/amd/am29xxxxxv2/current/include/am29xxxxx_dev.h b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/include/am29xxxxx_dev.h new file mode 100644 index 0000000..695b0da --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/include/am29xxxxx_dev.h @@ -0,0 +1,138 @@ +#ifndef CYGONCE_DEVS_FLASH_AM29xxxxx_dev_V2_H +# define CYGONCE_DEVS_FLASH_AM29xxxxx_dev_V2_H +//========================================================================== +// +// am29xxxxx_dev.h +// +// Flash driver for the AMD family - driver details +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2005 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: +// Date: 2004-11-05 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/devs_flash_amd_am29xxxxx_v2.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/io/flash.h> +#include <cyg/io/flash_dev.h> + +externC int cyg_am29xxxxx_read_devid_8( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_read_devid_16( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_read_devid_32( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_read_devid_88( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_read_devid_8888( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_read_devid_1616( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_read_devid_16as8( struct cyg_flash_dev*); + +externC int cyg_am29xxxxx_init_check_devid_8( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_check_devid_16( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_check_devid_32( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_check_devid_88( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_check_devid_8888( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_check_devid_1616( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_check_devid_16as8( struct cyg_flash_dev*); + +externC int cyg_am29xxxxx_init_cfi_8( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_cfi_16( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_cfi_32( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_cfi_88( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_cfi_8888( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_cfi_1616( struct cyg_flash_dev*); +externC int cyg_am29xxxxx_init_cfi_16as8( struct cyg_flash_dev*); + +externC int cyg_am29xxxxx_erase_8( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_am29xxxxx_erase_16( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_am29xxxxx_erase_32( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_am29xxxxx_erase_88( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_am29xxxxx_erase_8888( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_am29xxxxx_erase_1616( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_am29xxxxx_erase_16as8( struct cyg_flash_dev*, cyg_flashaddr_t); + +externC int cyg_am29xxxxx_program_8( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_am29xxxxx_program_16( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_am29xxxxx_program_32( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_am29xxxxx_program_88( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_am29xxxxx_program_8888( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_am29xxxxx_program_1616( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_am29xxxxx_program_16as8( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); + +externC int cyg_at49xxxx_softlock_8( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_softlock_16( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_softlock_32( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_softlock_88( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_softlock_8888( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_softlock_1616( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_softlock_16as8( struct cyg_flash_dev*, const cyg_flashaddr_t ); + +externC int cyg_at49xxxx_hardlock_8( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_hardlock_16( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_hardlock_32( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_hardlock_88( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_hardlock_8888( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_hardlock_1616( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_hardlock_16as8( struct cyg_flash_dev*, const cyg_flashaddr_t ); + +externC int cyg_at49xxxx_unlock_8( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_unlock_16( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_unlock_32( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_unlock_88( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_unlock_8888( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_unlock_1616( struct cyg_flash_dev*, const cyg_flashaddr_t ); +externC int cyg_at49xxxx_unlock_16as8( struct cyg_flash_dev*, const cyg_flashaddr_t ); + +// FIXME: add program_buffered() support as per e.g. the AM29LV128 +// FIXME: add software lock/unlock support as per e.g. the AM29BDS640 + +// The driver-specific data, pointed at by the priv field in a +// a cyg_flash_dev structure. +typedef struct cyg_am29xxxxx_dev { + // The device id, mainly for use by the init_check_devid() routines + cyg_uint32 devid; + // Space for the block_info fields needed for the cyg_flash_dev. + // These can be statically initialized, or dynamically via + // init_cfi(). + cyg_flash_block_info_t block_info[CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_REGIONS]; +} cyg_am29xxxxx_dev; + +// TODO: An AM29 specific macro could optimise the common case of CYG_FLASH_FUNS. +// Bart and Jifl discussed this in mid July/start Aug 2005. + +#endif // CYGONCE_DEVS_FLASH_AM29xxxxx_dev_V2_H diff --git a/ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c new file mode 100644 index 0000000..f6ebcd9 --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx.c @@ -0,0 +1,514 @@ +//========================================================================== +// +// am29xxxxx.c +// +// Flash driver for the AMD family +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: +// Date: 2004-11-05 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/devs_flash_amd_am29xxxxx_v2.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/infra/diag.h> +#include <cyg/io/flash.h> +#include <cyg/io/flash_dev.h> +#include <cyg/io/am29xxxxx_dev.h> +#include <cyg/hal/hal_arch.h> +#include <cyg/hal/hal_intr.h> +#include <cyg/hal/hal_cache.h> +#include <cyg/hal/hal_io.h> + +// This driver supports multiple banks of AMD am29xxxxx flash devices +// or compatibles. These are NOR-flash devices, requiring explicit +// erase operations with an erase value of 0xff. +// +// The devices may be 8-bit, 16-bit, or 32-bit (64-bit devices are not +// yet supported). Most but not all 16-bit devices can also be +// accessed as 8-bit, in which case the chip may be hooked up to an +// 8-bit bus. A bank of flash may involve just a single chip, or there +// may be several chips in parallel. Typical combinations are 88 to +// get 16-bit, 8888 for 32-bit, and 1616 for 32-bit. It is assumed +// that all chips within a bank are the same device. There may also be +// several banks of flash, and different banks may use different +// devices. +// +// This driver instantiates support for the various bus +// configurations: 8, 16, 16AS8, 32, 88, 8888, and 1616. On any given +// platform only one or two of these combinations will be of interest, +// but the remainder will be eliminated via linker garbage collection. +// To avoid excessive duplication an auxiliary file contains the +// actual implementations. Compiler optimization should eliminate any +// unnecessary code. + +// A flash driver is supposed to provide the following functions: +// int (*init)(...) +// size_t (*query)(...) +// int (*erase)(...) +// int (*program)(...) +// int (*block_lock)(...) +// int (*block_unlock)(...) +// +// The devices do not need any special initialization. However a given +// board may be manufactured with any one of several devices, which +// complicates things. The main complication is that there may be +// different bootsector layouts. The primary job of the init function +// is to check the device id, possibly fill in the bootsector info, +// or even to use the CFI support to get the bootsector info from the +// device itself. There may be other complications, e.g. minor variations +// of a given board design. These can be handled by h/w specific init +// functions in the platform HAL. +// +// The query function need not do anything useful, it is +// driver-defined. +// +// No read function need be supplied because the flash memory is +// always directly accessible to the cpu. +// +// Erase, program, and the locking functions need real +// implementations, although locking is not always available. + +// ---------------------------------------------------------------------------- +// The protocol understood by AMD flash chips and compatibles. +// The AM29_PARALLEL() macro is used in bus configurations with multiple +// devices in parallel, to issue commands to all the devices in a single +// write. In theory some of the operations, e.g. READ_DEVID, only need +// to access a single chip but then you get into complications for the +// SETUP commands. The AM29_SWAP() macro deals with endianness issues +// on some targets and can also help with h/w where things are just not +// wired right. +#define AM29_COMMAND_SETUP1 AM29_SWAP(AM29_PARALLEL(0x00AA)) +#define AM29_COMMAND_SETUP2 AM29_SWAP(AM29_PARALLEL(0x0055)) +#define AM29_COMMAND_RESET AM29_SWAP(AM29_PARALLEL(0x00F0)) +#define AM29_COMMAND_AUTOSELECT AM29_SWAP(AM29_PARALLEL(0x0090)) +#define AM29_COMMAND_ERASE AM29_SWAP(AM29_PARALLEL(0x0080)) +#define AM29_COMMAND_ERASE_SECTOR AM29_SWAP(AM29_PARALLEL(0x0030)) +#define AM29_COMMAND_ERASE_RESUME AM29_SWAP(AM29_PARALLEL(0x0030)) +#define AM29_COMMAND_CFI AM29_SWAP(AM29_PARALLEL(0x0098)) +#define AM29_COMMAND_PROGRAM AM29_SWAP(AM29_PARALLEL(0x00A0)) +// Following are specific to AT49 derivatives +#define AM29_COMMAND_AT49_SOFTLOCK_BLOCK_0 AM29_SWAP(AM29_PARALLEL(0x0080)) +#define AM29_COMMAND_AT49_SOFTLOCK_BLOCK_1 AM29_SWAP(AM29_PARALLEL(0x0040)) +#define AM29_COMMAND_AT49_HARDLOCK_BLOCK_0 AM29_SWAP(AM29_PARALLEL(0x0080)) +#define AM29_COMMAND_AT49_HARDLOCK_BLOCK_1 AM29_SWAP(AM29_PARALLEL(0x0060)) +#define AM29_COMMAND_AT49_UNLOCK_BLOCK AM29_SWAP(AM29_PARALLEL(0x0070)) + +// CFI offsets of interest. This assumes that the standard query table +// has not been replaced by the extended query table, although the +// CFI standard allows that behaviour. +#define AM29_OFFSET_CFI_Q AM29_OFFSET_CFI_DATA(0x0010) +#define AM29_OFFSET_CFI_SIZE AM29_OFFSET_CFI_DATA(0x0027) +#define AM29_OFFSET_CFI_BLOCK_REGIONS AM29_OFFSET_CFI_DATA(0x002C) +#define AM29_OFFSET_CFI_BLOCK_COUNT_LSB(_i_) AM29_OFFSET_CFI_DATA(0x002D + (4 * (_i_))) +#define AM29_OFFSET_CFI_BLOCK_COUNT_MSB(_i_) AM29_OFFSET_CFI_DATA(0x002E + (4 * (_i_))) +#define AM29_OFFSET_CFI_BLOCK_SIZE_LSB(_i_) AM29_OFFSET_CFI_DATA(0x002F + (4 * (_i_))) +#define AM29_OFFSET_CFI_BLOCK_SIZE_MSB(_i_) AM29_OFFSET_CFI_DATA(0x0030 + (4 * (_i_))) + +#define AM29_STATUS_DQ7 AM29_SWAP(AM29_PARALLEL(0x0080)) +#define AM29_STATUS_DQ6 AM29_SWAP(AM29_PARALLEL(0x0040)) +#define AM29_STATUS_DQ5 AM29_SWAP(AM29_PARALLEL(0x0020)) +#define AM29_STATUS_DQ4 AM29_SWAP(AM29_PARALLEL(0x0010)) +#define AM29_STATUS_DQ3 AM29_SWAP(AM29_PARALLEL(0x0008)) +#define AM29_STATUS_DQ2 AM29_SWAP(AM29_PARALLEL(0x0004)) +#define AM29_STATUS_DQ1 AM29_SWAP(AM29_PARALLEL(0x0002)) +#define AM29_STATUS_DQ0 AM29_SWAP(AM29_PARALLEL(0x0001)) +#define AM29_ID_LOCKED AM29_SWAP(AM29_PARALLEL(0x03)) + +// When programming the flash the source data may not be aligned +// correctly (although usually it will be). Hence it is necessary to +// construct the 16-bit or 32-bit numbers to be written to the flash +// from individual bytes, allowing for endianness. +#define AM29_NEXT_DATUM_8(_ptr_) (*_ptr_++) +#if CYG_BYTEORDER == CYG_LSBFIRST +# define AM29_NEXT_DATUM_16(_ptr_) \ + ({ \ + cyg_uint16 _result_; \ + _result_ = (_ptr_[1] << 8) | _ptr_[0]; \ + _ptr_ += 2; \ + _result_; }) + +# define AM29_NEXT_DATUM_32(_ptr_) \ + ({ \ + cyg_uint32 _result_; \ + _result_ = (_ptr_[3] << 24) | (_ptr_[2] << 16) | (_ptr_[1] << 8) | _ptr_[0]; \ + _ptr_ += 4; \ + _result_; }) +#else +# define AM29_NEXT_DATUM_16(_ptr_) \ + ({ \ + cyg_uint16 _result_; \ + _result_ = (_ptr_[0] << 8) | _ptr_[1]; \ + _ptr_ += 2; \ + _result_; }) + +# define AM29_NEXT_DATUM_32(_ptr_) \ + ({ \ + cyg_uint32 _result_; \ + _result_ = (_ptr_[0] << 24) | (_ptr_[1] << 16) | (_ptr_[2] << 8) | _ptr_[3]; \ + _ptr_ += 4; \ + _result_; }) + +#endif + +// The addresses used for programming the flash may be different from +// the ones used to read the flash. The macro +// HAL_AM29XXXXX_UNCACHED_ADDRESS() can be supplied by one of the HAL +// packages. Otherwise if CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY +// is not implemented then the macro CYGARC_UNCACHED_ADDRESS() +// will be used. If there is no way of bypassing the cache then +// the addresses will remain unchanged and instead the INTSCACHE +// macros will disable the cache. + +#if defined(HAL_AM29XXXXX_UNCACHED_ADDRESS) +# define AM29_UNCACHED_ADDRESS(_addr_) ((volatile AM29_TYPE*)HAL_AM29XXXXX_UNCACHED_ADDRESS(_addr_)) +#elif !defined(CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY) +# ifndef CYGARC_UNCACHED_ADDRESS +# error Cache should be bypassed but CYGARC_UNCACHED_ADDRESS is not defined. +# endif +# define AM29_UNCACHED_ADDRESS(_addr_) ((volatile AM29_TYPE*)CYGARC_UNCACHED_ADDRESS(_addr_)) +#elif defined(HAL_AM29XXXXX_P2V) +// HAL_AM29XXXXX_P2V is a deprecated macro that is only retained for +// backward compatibility. +# define AM29_UNCACHED_ADDRESS(_addr_) ((volatile AM29_TYPE*)HAL_AM29XXXXX_P2V(_addr_)) +#else +# define AM29_UNCACHED_ADDRESS(_addr_) ((volatile AM29_TYPE*)(_addr_)) +#endif + +// The bits on the data bus may need swapping, either because of +// endianness issues or because some lines are just wired wrong. +// SWAP is for commands going to the flash chip. UNSWAP is for +// data coming back from the flash chip. The swapping takes +// effect after allowing for AM29_PARALLEL(). Data is never +// swapped, it does not matter if bit 5 of a datum is actually +// stored in bit 3 of the flash as long as the data reads back +// right. +#if defined(HAL_AM29XXXXX_SWAP) +# define AM29_SWAP(_data_) HAL_AM29XXXXX_SWAP(_data_) +#else +# define AM29_SWAP(_data_) (_data_) +#endif +#if defined(HAL_AM29XXXXX_UNSWAP) +# define AM29_UNSWAP(_data_) HAL_AM29XXXXX_UNSWAP(_data_) +#else +# define AM29_UNSWAP(_data_) (_data_) +#endif + +// On some platforms there may be almost inexplicable failures, caused +// by very subtle effects such as instruction cache lines still being +// filled from flash memory which the _hw routines in .2ram sections are +// already running and have taken the flash out of read-array mode. +// These are very rare effects and not amenable to a generic solution, +// so instead the platform HAL (usually) can define additional hook +// macros that get invoked by the .2ram functions. These can e.g. +// add a short delay or invalidate a couple of instruction cache lines, +// but only if the code is executing from flash. Any such hooks will +// affect interrupt latency so should only be used when absolutely +// necessary. They must also be simple code, e.g. no calls to other +// functions that may be in flash. + +#ifdef HAL_AM29XXXXX_2RAM_ENTRY_HOOK +# define AM29_2RAM_ENTRY_HOOK() HAL_AM29XXXXX_2RAM_ENTRY_HOOK() +#else +# define AM29_2RAM_ENTRY_HOOK() CYG_EMPTY_STATEMENT +#endif +#ifdef HAL_AM29XXXXX_2RAM_EXIT_HOOK +# define AM29_2RAM_EXIT_HOOK() HAL_AM29XXXXX_2RAM_EXIT_HOOK() +#else +# define AM29_2RAM_EXIT_HOOK() CYG_EMPTY_STATEMENT +#endif + +// Cache and interrupt manipulation. This driver supports fine-grained +// control over interrupts and the cache, using three macros. These may +// be provided by the platform HAL, or by defaults here. There are +// three variants: +// +// 1) control both interrupts and cache. This is necessary if +// CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY is implemented, +// i.e. if the cache cannot be bypassed. The cache must be temporarily +// disabled for flash operations, and interrupts have to be disabled +// while the cache is disabled to prevent interrupts and context switches. +// 2) control interrupts only, the default if the cache can be bypassed +// when accessing the flash. The flash is still in an unusable +// state during flash operations so interrupts and context switches +// should be avoided. +// 3) only invalidate at the end, if the cache can be bypassed and the +// application guarantees that the flash will not be accessed by any interrupt +// handlers or other threads. + +#if defined(CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CACHED_ONLY) + +// First, the amount of state that should be preserved. By default +// this means the interrupt state and the data cache state. +# define AM29_INTSCACHE_DEFAULT_STATE int _saved_ints_, _saved_dcache_ + +// Start an operation on the flash. Make sure that interrupts are +// disabled and then save the current state of the data cache. The +// actual flash manipulation should happen with the cache disabled. +// There may still be data in the cache that has not yet been flushed +// to memory, so take care of that first. The invalidate the cache +// lines so that when the cache is re-enabled later on the processor +// gets everything from memory, rather than reusing old data in the +// cache. +# define AM29_INTSCACHE_DEFAULT_BEGIN() \ + CYG_MACRO_START \ + HAL_DISABLE_INTERRUPTS(_saved_ints_); \ + HAL_DCACHE_IS_ENABLED(_saved_dcache_); \ + HAL_DCACHE_SYNC(); \ + if (_saved_dcache_) { \ + HAL_DCACHE_DISABLE(); \ + } \ + HAL_DCACHE_INVALIDATE_ALL(); \ + CYG_MACRO_END + +// A flash operation has completed. Restore the situation to what it +// was before. Because of suspend/resume support interrupt handlers +// and other threads may have run, filling various cache lines with +// useful data. However it is assumed that none of those cache +// lines contain any of the data that has been manipulated by this +// flash operation (the stack and the flash block), so there is +// no need for another sync or invalidate. It is also assumed that +// we have not been executing any code out of the block of flash +// that has just been erased or programmed, so no need to worry +// about the icache. +#define AM29_INTSCACHE_DEFAULT_END() \ + CYG_MACRO_START \ + if (_saved_dcache_) { \ + HAL_DCACHE_ENABLE(); \ + } \ + HAL_RESTORE_INTERRUPTS(_saved_ints_); \ + CYG_MACRO_END + +#elif !defined(CYGIMP_DEVS_FLASH_AMD_AM29XXXXX_V2_LEAVE_INTERRUPTS_ENABLED) + +# define AM29_INTSCACHE_DEFAULT_STATE int _saved_ints_ +# define AM29_INTSCACHE_DEFAULT_BEGIN() HAL_DISABLE_INTERRUPTS(_saved_ints_) + +# if defined(HAL_DCACHE_SYNC) && defined(HAL_DCACHE_INVALIDATE_ALL) +// The following blips the interrupt enable to allow pending interrupts +// to run, which will reduce interrupt latency given the dcache sync/invalidate +// may be relatively lengthy. +# define AM29_INTSCACHE_DEFAULT_END() \ + CYG_MACRO_START \ + HAL_RESTORE_INTERRUPTS(_saved_ints_); \ + HAL_DISABLE_INTERRUPTS(_saved_ints_); \ + HAL_DCACHE_SYNC(); \ + HAL_DCACHE_INVALIDATE_ALL(); \ + HAL_RESTORE_INTERRUPTS(_saved_ints_); \ + CYG_MACRO_END +# else +# define AM29_INTSCACHE_DEFAULT_END() HAL_RESTORE_INTERRUPTS(_saved_ints_) +# endif +#else + +# define AM29_INTSCACHE_DEFAULT_STATE CYG_EMPTY_STATEMENT +# define AM29_INTSCACHE_DEFAULT_BEGIN() CYG_EMPTY_STATEMENT +# if defined(HAL_DCACHE_SYNC) && defined(HAL_DCACHE_INVALIDATE_ALL) +# define AM29_INTSCACHE_DEFAULT_END() \ + CYG_MACRO_START \ + int _saved_ints_; \ + HAL_DISABLE_INTERRUPTS(_saved_ints_); \ + HAL_DCACHE_SYNC(); \ + HAL_DCACHE_INVALIDATE_ALL(); \ + HAL_RESTORE_INTERRUPTS(_saved_ints_); \ + CYG_MACRO_END +# else +# define AM29_INTSCACHE_DEFAULT_END() CYG_EMPTY_STATEMENT +# endif +#endif + +#ifdef HAL_AM29XXXXX_INTSCACHE_STATE +# define AM29_INTSCACHE_STATE HAL_AM29XXXXX_INTSCACHE_STATE +#else +# define AM29_INTSCACHE_STATE AM29_INTSCACHE_DEFAULT_STATE +#endif +#ifdef HAL_AM29XXXXX_INTSCACHE_BEGIN +# define AM29_INTSCACHE_BEGIN HAL_AM29XXXXX_INTSCACHE_BEGIN +#else +# define AM29_INTSCACHE_BEGIN AM29_INTSCACHE_DEFAULT_BEGIN +#endif +#ifdef HAL_AM29XXXXX_INTSCACHE_END +# define AM29_INTSCACHE_END HAL_AM29XXXXX_INTSCACHE_END +#else +# define AM29_INTSCACHE_END AM29_INTSCACHE_DEFAULT_END +#endif + +// Some HALs require a special instruction to flush write buffers. +// Not all HALs do though, so we define it empty if it isn't already present. +#ifndef HAL_MEMORY_BARRIER +# define HAL_MEMORY_BARRIER() CYG_EMPTY_STATEMENT +#endif + +// ---------------------------------------------------------------------------- +// Generic code. + +// Get info about the current block, i.e. base and size. +static void +am29_get_block_info(struct cyg_flash_dev* dev, const cyg_flashaddr_t addr, cyg_flashaddr_t* block_start, size_t* block_size) +{ + cyg_uint32 i; + size_t offset = addr - dev->start; + cyg_flashaddr_t result; + + result = dev->start; + + for (i = 0; i < dev->num_block_infos; i++) { + if (offset < (dev->block_info[i].blocks * dev->block_info[i].block_size)) { + offset -= (offset % dev->block_info[i].block_size); + *block_start = result + offset; + *block_size = dev->block_info[i].block_size; + return; + } + result += (dev->block_info[i].blocks * dev->block_info[i].block_size); + offset -= (dev->block_info[i].blocks * dev->block_info[i].block_size); + } + CYG_FAIL("Address out of range of selected flash device"); +} + +// ---------------------------------------------------------------------------- +// Instantiate all of the h/w functions appropriate for the various +// configurations. +// The suffix is used to construct the function names. +// Types for the width of the bus, controlling the granularity of access. +// devcount specifies the number of devices in parallel, and is used for looping +// The NEXT_DATUM() macro allows for misaligned source data. +// The PARALLEL macro, if defined, is used for sending commands and reading +// status bits from all devices in the bank in one operation. + +// A single 8-bit device on an 8-bit bus. +#define AM29_SUFFIX 8 +#define AM29_TYPE cyg_uint8 +#define AM29_DEVCOUNT 1 +#define AM29_NEXT_DATUM(_ptr_) AM29_NEXT_DATUM_8(_ptr_) + +#include "am29xxxxx_aux.c" + +#undef AM29_SUFFIX +#undef AM29_TYPE +#undef AM29_DEVCOUNT +#undef AM29_NEXT_DATUM + +// A single 16-bit device. +#define AM29_SUFFIX 16 +#define AM29_TYPE cyg_uint16 +#define AM29_DEVCOUNT 1 +#define AM29_NEXT_DATUM(_ptr_) AM29_NEXT_DATUM_16(_ptr_) + +#include "am29xxxxx_aux.c" + +#undef AM29_SUFFIX +#undef AM29_TYPE +#undef AM29_DEVCOUNT +#undef AM29_NEXT_DATUM + +// A single 32-bit device. +#define AM29_SUFFIX 32 +#define AM29_TYPE cyg_uint32 +#define AM29_DEVCOUNT 1 +#define AM29_NEXT_DATUM(_ptr_) AM29_NEXT_DATUM_32(_ptr_) + +#include "am29xxxxx_aux.c" + +#undef AM29_SUFFIX +#undef AM29_TYPE +#undef AM29_DEVCOUNT +#undef AM29_NEXT_DATUM + +// Two 8-bit devices, giving a 16-bit bus. +#define AM29_SUFFIX 88 +#define AM29_TYPE cyg_uint16 +#define AM29_DEVCOUNT 2 +#define AM29_NEXT_DATUM(_ptr_) AM29_NEXT_DATUM_16(_ptr_) +#define AM29_PARALLEL(_cmd_) ((_cmd_ << 8) | _cmd_) + +#include "am29xxxxx_aux.c" + +#undef AM29_SUFFIX +#undef AM29_TYPE +#undef AM29_DEVCOUNT +#undef AM29_NEXT_DATUM + +// Four 8-bit devices, giving a 32-bit bus. +#define AM29_SUFFIX 8888 +#define AM29_TYPE cyg_uint32 +#define AM29_DEVCOUNT 4 +#define AM29_NEXT_DATUM(_ptr_) AM29_NEXT_DATUM_32(_ptr_) +#define AM29_PARALLEL(_cmd_) ((_cmd_ << 24) | (_cmd_ << 16) | (_cmd_ << 8) | _cmd_) + +#include "am29xxxxx_aux.c" + +#undef AM29_SUFFIX +#undef AM29_TYPE +#undef AM29_DEVCOUNT +#undef AM29_NEXT_DATUM + +// Two 16-bit devices, giving a 32-bit bus. +#define AM29_SUFFIX 1616 +#define AM29_TYPE cyg_uint32 +#define AM29_DEVCOUNT 2 +#define AM29_NEXT_DATUM(_ptr_) AM29_NEXT_DATUM_32(_ptr_) +#define AM29_PARALLEL(_cmd_) ((_cmd_ << 16) | _cmd_) + +#include "am29xxxxx_aux.c" + +#undef AM29_SUFFIX +#undef AM29_TYPE +#undef AM29_DEVCOUNT +#undef AM29_NEXT_DATUM + +// 16AS8. A 16-bit device hooked up so that only byte accesses are +// allowed. This requires unusual offsets +#define AM29_SUFFIX 16as8 +#define AM29_TYPE cyg_uint8 +#define AM29_DEVCOUNT 1 +#define AM29_NEXT_DATUM(_ptr_) AM29_NEXT_DATUM_8(_ptr_) +#define AM29_OFFSET_COMMAND 0x0AAA +#define AM29_OFFSET_COMMAND2 0x0555 +#define AM29_OFFSET_MANUFACTURER_ID 0x0000 +#define AM29_OFFSET_DEVID 0x0002 +#define AM29_OFFSET_DEVID2 0x001C +#define AM29_OFFSET_DEVID3 0x001E +#define AM29_OFFSET_AT49_LOCK_STATUS 04 +#define AM29_OFFSET_CFI 0x00AA +#define AM29_OFFSET_CFI_DATA(_idx_) (2 * (_idx_)) + +#include "am29xxxxx_aux.c" diff --git a/ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c new file mode 100644 index 0000000..c5f392c --- /dev/null +++ b/ecos/packages/devs/flash/amd/am29xxxxxv2/current/src/am29xxxxx_aux.c @@ -0,0 +1,985 @@ +//========================================================================== +// +// am29xxxxx_aux.c +// +// Flash driver for the AMD family - implementation. +// +//========================================================================== +// ####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +// +// eCos 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 or (at your option) any later +// version. +// +// eCos 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 eCos; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +// As a special exception, if other files instantiate templates or use +// macros or inline functions from this file, or you compile this file +// and link it with other works to produce a work based on this file, +// this file does not by itself cause the resulting work to be covered by +// the GNU General Public License. However the source code for this file +// must still be made available in accordance with section (3) of the GNU +// General Public License v2. +// +// This exception does not invalidate any other reasons why a work based +// on this file might be covered by the GNU General Public License. +// ------------------------------------------- +// ####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): bartv +// Contributors: +// Date: 2004-11-05 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// This file is #include'd multiple times from the main am29xxxxx.c file, +// It serves to instantiate the various hardware operations in ways +// appropriate for all the bus configurations. + +// The following macros are used to construct suitable function names +// for the current bus configuration. AM29_SUFFIX is #define'd before +// each #include of am29xxxxx_aux.c + +#ifndef AM29_STR +# define AM29_STR1(_a_) # _a_ +# define AM29_STR(_a_) AM29_STR1(_a_) +# define AM29_CONCAT3_AUX(_a_, _b_, _c_) _a_##_b_##_c_ +# define AM29_CONCAT3(_a_, _b_, _c_) AM29_CONCAT3_AUX(_a_, _b_, _c_) +#endif + +#define AM29_FNNAME(_base_) AM29_CONCAT3(_base_, _, AM29_SUFFIX) + +// Similarly construct a forward declaration, placing the function in +// the .2ram section. Each function must still be in a separate section +// for linker garbage collection. + +# define AM29_RAMFNDECL(_base_, _args_) \ + AM29_FNNAME(_base_) _args_ __attribute__((section (".2ram." AM29_STR(_base_) "_" AM29_STR(AM29_SUFFIX)))) + +// Calculate the various offsets, based on the device count. +// The main code may override these settings for specific +// configurations, e.g. 16as8 +#ifndef AM29_OFFSET_COMMAND +# define AM29_OFFSET_COMMAND 0x0555 +#endif +#ifndef AM29_OFFSET_COMMAND2 +# define AM29_OFFSET_COMMAND2 0x02AA +#endif +#ifndef AM29_OFFSET_MANUFACTURER_ID +# define AM29_OFFSET_MANUFACTURER_ID 0x0000 +#endif +#ifndef AM29_OFFSET_DEVID +# define AM29_OFFSET_DEVID 0x0001 +#endif +#ifndef AM29_OFFSET_DEVID2 +# define AM29_OFFSET_DEVID2 0x000E +#endif +#ifndef AM29_OFFSET_DEVID3 +# define AM29_OFFSET_DEVID3 0x000F +#endif +#ifndef AM29_OFFSET_CFI +# define AM29_OFFSET_CFI 0x0055 +#endif +#ifndef AM29_OFFSET_CFI_DATA +# define AM29_OFFSET_CFI_DATA(_idx_) _idx_ +#endif +#ifndef AM29_OFFSET_AT49_LOCK_STATUS +# define AM29_OFFSET_AT49_LOCK_STATUS 0x02 +#endif + +// For parallel operation commands are issued in parallel and status +// bits are checked in parallel. +#ifndef AM29_PARALLEL +# define AM29_PARALLEL(_cmd_) (_cmd_) +#endif + +// ---------------------------------------------------------------------------- +// Diagnostic routines. + +#if 0 +#define amd_diag( __fmt, ... ) diag_printf("AMD: %s[%d]: " __fmt, __FUNCTION__, __LINE__, ## __VA_ARGS__ ); +#define amd_dump_buf( __addr, __size ) diag_dump_buf( __addr, __size ) +#else +#define amd_diag( __fmt, ... ) +#define amd_dump_buf( __addr, __size ) +#endif + +// ---------------------------------------------------------------------------- +// When performing the various low-level operations like erase the flash +// chip can no longer support ordinary data reads. Obviously this is a +// problem if the current code is executing out of flash. The solution is +// to store the key functions in RAM rather than flash, via a special +// linker section .2ram which usually gets placed in the same area as +// .data. +// +// In a ROM startup application anything in .2ram will consume space +// in both the flash and RAM. Hence it is desirable to keep the .2ram +// functions as small as possible, responsible only for the actual +// hardware manipulation. +// +// All these .2ram functions should be invoked with interrupts +// disabled. Depending on the hardware it may also be necessary to +// have the data cache disabled. The .2ram functions must be +// self-contained, even macro invocations like HAL_DELAY_US() are +// banned because on some platforms those could be implemented as +// function calls. + +// gcc requires forward declarations with the attributes, then the actual +// definitions. +static int AM29_RAMFNDECL(am29_hw_query, (volatile AM29_TYPE*)); +static int AM29_RAMFNDECL(am29_hw_cfi, (struct cyg_flash_dev*, cyg_am29xxxxx_dev*, volatile AM29_TYPE*)); +static int AM29_RAMFNDECL(am29_hw_erase, (volatile AM29_TYPE*)); +static int AM29_RAMFNDECL(am29_hw_program, (volatile AM29_TYPE*, volatile AM29_TYPE*, const cyg_uint8*, cyg_uint32 count, int retries)); +static int AM29_RAMFNDECL(at49_hw_softlock, (volatile AM29_TYPE*)); +static int AM29_RAMFNDECL(at49_hw_hardlock, (volatile AM29_TYPE*)); +static int AM29_RAMFNDECL(at49_hw_unlock, (volatile AM29_TYPE*)); + + +// ---------------------------------------------------------------------------- + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_RESET_NEEDS_RESUME +// With this flash component (e.g. AT49xxxxx), the reset does not +// cause a suspended erase/program to be aborted. Instead all we +// can do is resume any suspended operations. We do this on each +// block as some parts have different granularity. + +static void +AM29_FNNAME(am29_hw_force_all_suspended_resume)(struct cyg_flash_dev* dev, cyg_am29xxxxx_dev* am29_dev, volatile AM29_TYPE* addr) +{ + cyg_ucount16 i,j; + AM29_TYPE datum1, datum2; + + AM29_2RAM_ENTRY_HOOK(); + + for (i=0; i<dev->num_block_infos; i++) + { + for (j=0; j<am29_dev->block_info[i].blocks; j++) + { + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_ERASE_RESUME; + HAL_MEMORY_BARRIER(); + // We don't know if the suspended operation was an erase or + // program, so just compare the whole word to spot _any_ toggling. + do { + datum1 = addr[AM29_OFFSET_COMMAND]; + datum2 = addr[AM29_OFFSET_COMMAND]; + } while (datum1 != datum2); + + addr += am29_dev->block_info[i].block_size/sizeof(AM29_TYPE); + } + } + + AM29_2RAM_EXIT_HOOK(); +} +#endif // ifdef CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_RESET_NEEDS_RESUME + +// Read the device id. This involves a straightforward command +// sequence, followed by a reset to get back into array mode. +// All chips are accessed in parallel, but only the response +// from the least significant is used. +static int +AM29_FNNAME(am29_hw_query)(volatile AM29_TYPE* addr) +{ + int devid; + cyg_uint32 onedevmask; + + AM29_2RAM_ENTRY_HOOK(); + + // Fortunately the compiler should optimise the below + // tests such that onedevmask is a constant. + if ( 1 == (sizeof(AM29_TYPE) / AM29_DEVCOUNT) ) + onedevmask = 0xFF; + else if ( 2 == (sizeof(AM29_TYPE) / AM29_DEVCOUNT) ) + onedevmask = 0xFFFF; + else { + CYG_ASSERT( 4 == (sizeof(AM29_TYPE) / AM29_DEVCOUNT), + "Unexpected flash width per device" ); + onedevmask = 0xFFFFFFFF; + } + + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_AUTOSELECT; + HAL_MEMORY_BARRIER(); + + devid = AM29_UNSWAP(addr[AM29_OFFSET_DEVID]) & onedevmask; + +// amd_diag("devid %x\n", devid ); +// amd_dump_buf(addr, 64 ); + + // The original AMD chips only used a single-byte device id, but + // all codes have now been used up. Newer devices use a 3-byte + // devid. The above devid read will have returned 0x007E. The + // test allows for boards with a mixture of old and new chips. + // The amount of code involved is too small to warrant a config + // option. + // FIXME by jifl: What happens when a single device is connected 16-bits + // (or 32-bits) wide per device? Is the code still 0x7E, and all the + // other devids are 8-bits only? + if (0x007E == devid) { + devid <<= 16; + devid |= ((AM29_UNSWAP(addr[AM29_OFFSET_DEVID2]) & 0x00FF) << 8); + devid |= (AM29_UNSWAP(addr[AM29_OFFSET_DEVID3]) & 0x00FF); + } + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + +// amd_diag("devid %x\n", devid ); + + AM29_2RAM_EXIT_HOOK(); + return devid; +} + +// Perform a CFI query. This involves placing the device(s) into CFI +// mode, checking that this has really happened, and then reading the +// size and block info. The address corresponds to the start of the +// flash. +static int +AM29_FNNAME(am29_hw_cfi)(struct cyg_flash_dev* dev, cyg_am29xxxxx_dev* am29_dev, volatile AM29_TYPE* addr) +{ + int dev_size; + int i; + int erase_regions; + + AM29_2RAM_ENTRY_HOOK(); + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CFI_BOGOSITY + int manufacturer_id; + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_AUTOSELECT; + HAL_MEMORY_BARRIER(); + + manufacturer_id = AM29_UNSWAP(addr[AM29_OFFSET_MANUFACTURER_ID]) & 0x00FF; + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); +#endif + + // Just a single write is needed to put the device into CFI mode + addr[AM29_OFFSET_CFI] = AM29_COMMAND_CFI; + HAL_MEMORY_BARRIER(); +// amd_diag("CFI data:\n"); +// amd_dump_buf( addr, 256 ); + // Now check that we really are in CFI mode. There should be a 'Q' + // at a specific address. This test is not 100% reliable, but should + // be good enough. + if ('Q' != (AM29_UNSWAP(addr[AM29_OFFSET_CFI_Q]) & 0x00FF)) { + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + AM29_2RAM_EXIT_HOOK(); + return CYG_FLASH_ERR_PROTOCOL; + } + // Device sizes are always a power of 2, and the shift is encoded + // in a single byte + dev_size = 0x01 << (AM29_UNSWAP(addr[AM29_OFFSET_CFI_SIZE]) & 0x00FF); + dev->end = dev->start + dev_size - 1; + + // The number of erase regions is also encoded in a single byte. + // Usually this is no more than 4. A value of 0 indicates that + // only chip erase is supported, but the driver does not cope + // with that. + erase_regions = AM29_UNSWAP(addr[AM29_OFFSET_CFI_BLOCK_REGIONS]) & 0x00FF; + if (erase_regions > CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_REGIONS) { + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + AM29_2RAM_EXIT_HOOK(); + return CYG_FLASH_ERR_PROTOCOL; + } + dev->num_block_infos = erase_regions; + + for (i = 0; i < erase_regions; i++) { + cyg_uint32 count, size; + cyg_uint32 count_lsb = AM29_UNSWAP(addr[AM29_OFFSET_CFI_BLOCK_COUNT_LSB(i)]) & 0x00FF; + cyg_uint32 count_msb = AM29_UNSWAP(addr[AM29_OFFSET_CFI_BLOCK_COUNT_MSB(i)]) & 0x00FF; + cyg_uint32 size_lsb = AM29_UNSWAP(addr[AM29_OFFSET_CFI_BLOCK_SIZE_LSB(i)]) & 0x00FF; + cyg_uint32 size_msb = AM29_UNSWAP(addr[AM29_OFFSET_CFI_BLOCK_SIZE_MSB(i)]) & 0x00FF; + + count = ((count_msb << 8) | count_lsb) + 1; + size = (size_msb << 16) | (size_lsb << 8); + am29_dev->block_info[i].block_size = (size_t) size * AM29_DEVCOUNT; + am29_dev->block_info[i].blocks = count; + } + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_CFI_BOGOSITY + + // Some flash parts have a peculiar implementation of CFI. The + // device erase regions may not be in the order specified in the + // main CFI area. Instead the erase regions are given in a + // manufacturer dependent fixed order, regardless of whether this + // is a top or bottom boot block device. A vendor-specific + // extended query block has an entry saying whether the boot + // blocks are at the top or bottom. This code works out whether + // the erase regions appear to be specified in the wrong order, + // and then swaps them over. + + { + enum { bottom, symmetric, top } boot_type = symmetric; + cyg_uint32 vspec = AM29_SWAP(addr[AM29_OFFSET_CFI_DATA(0x15)]) & 0x00FF; + + // Take a look at the vendor specific area for the boot block + // order. + + switch( manufacturer_id ) + { + // Atmel appear to have their own layout for the vendor + // specific area. Offset 0x06 of the vendor specific area + // contains a single bit: 0x00 = top boot, 0x01 = bottom + // boot. There appears to be no way of specifying + // symmetric formats. + case 0x1F: + if( (addr[AM29_OFFSET_CFI_DATA(vspec+0x06)] & AM29_SWAP(0x1)) == AM29_SWAP(0x1) ) + boot_type = bottom; + else boot_type = top; + break; + + // Most other manufacturers seem to follow the same layout + // and encoding. Offset 0xF of the vendor specific area + // contains the boot sector layout: 0x00 = uniform, 0x01 = + // 8x8k top and bottom, 0x02 = bottom boot, 0x03 = top + // boot, 0x04 = both top and bottom. + // + // The following manufacturers support this layout: + // AMD, Spansion, ST, Macronix. + default: + if( (addr[AM29_OFFSET_CFI_DATA(vspec+0xF)] == AM29_SWAP(0x2)) ) + boot_type = bottom; + else if( (addr[AM29_OFFSET_CFI_DATA(vspec+0xF)] == AM29_SWAP(0x3)) ) + boot_type = top; + // All other options are symmetric + break; + } + + // If the device is marked as top boot, but the erase region + // list appears to be in bottom boot order, then reverse the + // list. Also swap, if it is marked as bottom boot but the + // erase regions appear to be in top boot order. This code + // assumes that the first boot block is always smaller than + // regular blocks; it is possible to imagine flash layouts for + // which that is not true. + + if( ((boot_type == top) && + (am29_dev->block_info[0].block_size < am29_dev->block_info[erase_regions-1].block_size)) || + ((boot_type == bottom) && + (am29_dev->block_info[0].block_size > am29_dev->block_info[erase_regions-1].block_size))) + { + int lo, hi; + + for( lo = 0, hi = erase_regions-1 ; lo < hi ; lo++, hi-- ) + { + size_t size = am29_dev->block_info[lo].block_size; + cyg_uint32 count = am29_dev->block_info[lo].blocks; + am29_dev->block_info[lo].block_size = am29_dev->block_info[hi].block_size; + am29_dev->block_info[lo].blocks = am29_dev->block_info[hi].blocks; + am29_dev->block_info[hi].block_size = size; + am29_dev->block_info[hi].blocks = count; + } + } + } +#endif + + // Get out of CFI mode + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + + AM29_2RAM_EXIT_HOOK(); + return CYG_FLASH_ERR_OK; +} + +// Erase a single sector. There is no API support for chip-erase. The +// generic code operates one sector at a time, invoking the driver for +// each sector, so there is no opportunity inside the driver for +// erasing multiple sectors in a single call. The address argument +// points at the start of the sector. +static int +AM29_FNNAME(am29_hw_erase)(volatile AM29_TYPE* addr) +{ + int retries; + AM29_TYPE datum; + + AM29_2RAM_ENTRY_HOOK(); + + // Start the erase operation + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_ERASE; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_ERASE_SECTOR; + HAL_MEMORY_BARRIER(); + // There is now a 50us window in which we could send additional + // ERASE_SECTOR commands, but the driver API does not allow this + + // All chips are now erasing in parallel. Loop until all have + // completed. This can be detected in a number of ways. The DQ7 + // bit will be 0 until the erase is complete, but there is a + // problem if something went wrong (e.g. the sector is locked), + // the erase has not actually started, and the relevant bit was 0 + // already. More useful is DQ6. This will toggle during the 50us + // window and while the erase is in progress, then stop toggling. + // If the erase does not actually start then the bit won't toggle + // at all so the operation completes rather quickly. + // + // If at any time DQ5 is set (indicating a timeout inside the + // chip) then a reset command must be issued and the erase is + // aborted. It is not clear this can actually happen during an + // erase, but just in case. + for (retries = CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_ERASE_TIMEOUT; + retries > 0; + retries--) { + + datum = addr[AM29_OFFSET_COMMAND]; + // The operation completes when all DQ7 bits are set. + if ((datum & AM29_STATUS_DQ7) == AM29_STATUS_DQ7) { + break; + } + // Otherwise, for any flash chips where DQ7 is still clear, it is + // necessary to test DQ5. + if (((datum ^ AM29_STATUS_DQ7) >> 2) & datum & AM29_STATUS_DQ5) { + // DQ5 is set, indicating a hardware error. The calling code + // will always verify that the erase really was successful + // so we do not need to distinguish between error conditions. + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + break; + } + } + + // A result of 0 indicates a timeout. + // A non-zero result indicates + // that the erase completed or there has been a fatal error. + AM29_2RAM_EXIT_HOOK(); + return retries; +} + +// Write data to flash. At most one block will be processed at a time, +// but the write may be for a subset of the write. The destination +// address will be aligned in a way suitable for the bus. The source +// address need not be aligned. The count is in AM29_TYPE's, i.e. +// as per the bus alignment, not in bytes. +static int +AM29_FNNAME(am29_hw_program)(volatile AM29_TYPE* block_start, volatile AM29_TYPE* addr, const cyg_uint8* buf, cyg_uint32 count, int retries) +{ + int i; + + AM29_2RAM_ENTRY_HOOK(); + + for (i = 0; (i < count) && (retries > 0); i++) { + AM29_TYPE datum, current, active_dq7s; + + // We can only clear bits, not set them, so any bits that were + // already clear need to be preserved. + current = addr[i]; + datum = AM29_NEXT_DATUM(buf) & current; + if (datum == current) { + // No change, so just move on. + continue; + } + + block_start[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + block_start[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + block_start[AM29_OFFSET_COMMAND] = AM29_COMMAND_PROGRAM; + HAL_MEMORY_BARRIER(); + addr[i] = datum; + HAL_MEMORY_BARRIER(); + + // The data is now being written. The official algorithm is + // to poll either DQ7 or DQ6, checking DQ5 along the way for + // error conditions. This gets complicated with parallel + // flash chips because they may finish at different times. + // The alternative approach is to ignore the status bits + // completely and just look for current==datum until the + // retry count is exceeded. However that does not cope + // cleanly with cases where the flash chip reports an error + // early on, e.g. because a flash block is locked. + + while (--retries > 0) { +#if CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_DELAY > 0 + // Some chips want a delay between polling + { int j; for( j = 0; j < CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_DELAY; j++ ); } +#endif + // While the program operation is in progress DQ7 will read + // back inverted from datum. + current = addr[i]; + if ((current & AM29_STATUS_DQ7) == (datum & AM29_STATUS_DQ7)) { + // All DQ7 bits now match datum, so the operation has completed. + // But not necessarily successfully. On some chips DQ7 may + // toggle before DQ0-6 are valid, so we need to read the + // data one more time. + current = addr[i]; + if (current != datum) { + retries = 0; // Abort this burst. + } + break; + } + + // Now we want to check the DQ5 status bits, but only for those + // chips which are still programming. ((current^datum) & DQ7) gives + // ones for chips which are still programming, zeroes for chips when + // the programming is complete. + active_dq7s = (current ^ datum) & AM29_STATUS_DQ7; + + if (0 != (current & (active_dq7s >> 2))) { + // Unfortunately this is not sufficient to prove an error. On + // some chips DQ0-6 switch to the data while DQ7 is still a + // status flag, so the set DQ5 bit detected above may be data + // instead of an error. Check again, this time DQ7 may + // indicate completion. + // + // Next problem. Suppose chip A gave a bogus DQ5 result earlier + // because it was just finishing. For this read chip A gives + // back datum, but now chip B is finishing and has reported a + // bogus DQ5. + // + // Solution: if any of the DQ7 lines have changed since the last + // time, go around the loop again. When an error occurs DQ5 + // remains set and DQ7 remains toggled, so there is no harm + // in one more polling loop. + + current = addr[i]; + if (((current ^ datum) & AM29_STATUS_DQ7) != active_dq7s) { + continue; + } + + // DQ5 has been set in a chip where DQ7 indicates an ongoing + // program operation for two successive reads. That is an error. + // The hardware is in a strange state so must be reset. + block_start[AM29_OFFSET_COMMAND] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + retries = 0; + break; + } + // No DQ5 bits set in chips which are still programming. Poll again. + } // Retry for current word + } // Next word + + // At this point retries holds the total number of retries left. + // 0 indicates a timeout or fatal error. + // >0 indicates success. + AM29_2RAM_EXIT_HOOK(); + return retries; +} + +// FIXME: implement a separate program routine for buffered writes. + +#if 0 +// Unused for now, but might be useful later +static int +AM29_FNNAME(at49_hw_is_locked)(volatile AM29_TYPE* addr) +{ + int result; + AM29_TYPE plane; + + AM29_2RAM_ENTRY_HOOK(); + + // Plane is bits A21-A20 for AT49BV6416 + // A more generic formula is needed. + plane = AM29_PARALLEL( ((((CYG_ADDRESS)addr)>>21) & 0x3) ); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND + plane] = AM29_COMMAND_AUTOSELECT; + HAL_MEMORY_BARRIER(); + result = addr[AM29_OFFSET_AT49_LOCK_STATUS]; + addr[0] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + // The bottom two bits hold the lock status, LSB indicates + // soft lock, next bit indicates hard lock. We don't distinguish + // in this function. + AM29_2RAM_EXIT_HOOK(); + return (0 != (result & AM29_ID_LOCKED)); +} +#endif + +static int +AM29_FNNAME(at49_hw_softlock)(volatile AM29_TYPE* addr) +{ + int result = CYG_FLASH_ERR_OK; + + AM29_2RAM_ENTRY_HOOK(); + + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_AT49_SOFTLOCK_BLOCK_0; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[0] = AM29_COMMAND_AT49_SOFTLOCK_BLOCK_1; + HAL_MEMORY_BARRIER(); + // not sure if this is required: + addr[0] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + AM29_2RAM_EXIT_HOOK(); + return result; +} + +static int +AM29_FNNAME(at49_hw_hardlock)(volatile AM29_TYPE* addr) +{ + int result = CYG_FLASH_ERR_OK; + + AM29_2RAM_ENTRY_HOOK(); + + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_AT49_HARDLOCK_BLOCK_0; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[AM29_OFFSET_COMMAND2] = AM29_COMMAND_SETUP2; + HAL_MEMORY_BARRIER(); + addr[0] = AM29_COMMAND_AT49_HARDLOCK_BLOCK_1; + HAL_MEMORY_BARRIER(); + // not sure if this is required: + addr[0] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + AM29_2RAM_EXIT_HOOK(); + return result; +} + +static int +AM29_FNNAME(at49_hw_unlock)(volatile AM29_TYPE* addr) +{ + int result = CYG_FLASH_ERR_OK; + + AM29_2RAM_ENTRY_HOOK(); + + addr[AM29_OFFSET_COMMAND] = AM29_COMMAND_SETUP1; + HAL_MEMORY_BARRIER(); + addr[0] = AM29_COMMAND_AT49_UNLOCK_BLOCK; + HAL_MEMORY_BARRIER(); + // not sure if this is required: + addr[0] = AM29_COMMAND_RESET; + HAL_MEMORY_BARRIER(); + AM29_2RAM_EXIT_HOOK(); + return result; +} + + +// ---------------------------------------------------------------------------- +// Exported code, mostly for placing in a cyg_flash_dev_funs structure. + +// Just read the device id, either for sanity checking that the system +// has been configured for the right device, or for filling in the +// block info by a platform-specific init routine if the platform may +// be manufactured with one of several different chips. +int +AM29_FNNAME(cyg_am29xxxxx_read_devid) (struct cyg_flash_dev* dev) +{ + int (*query_fn)(volatile AM29_TYPE*); + int devid; + volatile AM29_TYPE* addr; + AM29_INTSCACHE_STATE; + + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + + amd_diag("\n"); + + addr = AM29_UNCACHED_ADDRESS(dev->start); + query_fn = (int (*)(volatile AM29_TYPE*)) cyg_flash_anonymizer( & AM29_FNNAME(am29_hw_query) ); + AM29_INTSCACHE_BEGIN(); + devid = (*query_fn)(addr); + AM29_INTSCACHE_END(); + return devid; +} + +// Validate that the device statically configured is the one on the +// board. +int +AM29_FNNAME(cyg_am29xxxxx_init_check_devid)(struct cyg_flash_dev* dev) +{ + cyg_am29xxxxx_dev* am29_dev; + int devid; + + amd_diag("\n"); + + am29_dev = (cyg_am29xxxxx_dev*) dev->priv; + devid = AM29_FNNAME(cyg_am29xxxxx_read_devid)(dev); + if (devid != am29_dev->devid) { + return CYG_FLASH_ERR_DRV_WRONG_PART; + } + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_RESET_NEEDS_RESUME + { + volatile AM29_TYPE *addr = AM29_UNCACHED_ADDRESS(dev->start); + void (*resume_fn)(struct cyg_flash_dev*, cyg_am29xxxxx_dev*, volatile AM29_TYPE*); + resume_fn = (void (*)(struct cyg_flash_dev*, cyg_am29xxxxx_dev*, volatile AM29_TYPE*)) + cyg_flash_anonymizer( &AM29_FNNAME(am29_hw_force_all_suspended_resume) ); + AM29_INTSCACHE_STATE; + + AM29_INTSCACHE_BEGIN(); + (*resume_fn)(dev, am29_dev, addr); + AM29_INTSCACHE_END(); + } +#endif + + // Successfully queried the device, and the id's match. That + // should be a good enough indication that the flash is working. + return CYG_FLASH_ERR_OK; +} + +// Initialize via a CFI query, instead of statically specifying the +// boot block layout. +int +AM29_FNNAME(cyg_am29xxxxx_init_cfi)(struct cyg_flash_dev* dev) +{ + int (*cfi_fn)(struct cyg_flash_dev*, cyg_am29xxxxx_dev*, volatile AM29_TYPE*); + volatile AM29_TYPE* addr; + cyg_am29xxxxx_dev* am29_dev; + int result; + AM29_INTSCACHE_STATE; + + amd_diag("\n"); + + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + am29_dev = (cyg_am29xxxxx_dev*) dev->priv; // Remove const, only place where this is needed. + addr = AM29_UNCACHED_ADDRESS(dev->start); + cfi_fn = (int (*)(struct cyg_flash_dev*, cyg_am29xxxxx_dev*, volatile AM29_TYPE*)) + cyg_flash_anonymizer( & AM29_FNNAME(am29_hw_cfi)); + + AM29_INTSCACHE_BEGIN(); + result = (*cfi_fn)(dev, am29_dev, addr); + AM29_INTSCACHE_END(); + + // Now calculate the device size, and hence the end field. + if (CYG_FLASH_ERR_OK == result) { + int i; + int size = 0; + for (i = 0; i < dev->num_block_infos; i++) { + amd_diag("region %d: 0x%08x * %d\n", i, (int)dev->block_info[i].block_size, dev->block_info[i].blocks ); + size += (dev->block_info[i].block_size * dev->block_info[i].blocks); + } + dev->end = dev->start + size - 1; + +#ifdef CYGHWR_DEVS_FLASH_AMD_AM29XXXXX_V2_RESET_NEEDS_RESUME + { + void (*resume_fn)(struct cyg_flash_dev*, cyg_am29xxxxx_dev*, volatile AM29_TYPE*); + resume_fn = (void (*)(struct cyg_flash_dev*, cyg_am29xxxxx_dev*, volatile AM29_TYPE*)) + cyg_flash_anonymizer( &AM29_FNNAME(am29_hw_force_all_suspended_resume) ); + + AM29_INTSCACHE_BEGIN(); + (*resume_fn)(dev, am29_dev, addr); + AM29_INTSCACHE_END(); + } +#endif + } + return result; +} + +// Erase a single block. The calling code will have supplied a pointer +// aligned to a block boundary. +int +AM29_FNNAME(cyg_am29xxxxx_erase)(struct cyg_flash_dev* dev, cyg_flashaddr_t addr) +{ + int (*erase_fn)(volatile AM29_TYPE*); + volatile AM29_TYPE* block; + cyg_flashaddr_t block_start; + size_t block_size; + int i; + int result; + AM29_INTSCACHE_STATE; + + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + CYG_ASSERT((addr >= dev->start) && (addr <= dev->end), "flash address out of device range"); + + am29_get_block_info(dev, addr, &block_start, &block_size); + CYG_ASSERT(addr == block_start, "erase address should be the start of a flash block"); + + amd_diag("addr %p block %p[%d]\n", (void*)addr, (void*)block_start, (int)block_size ); + + block = AM29_UNCACHED_ADDRESS(addr); + erase_fn = (int (*)(volatile AM29_TYPE*)) cyg_flash_anonymizer( & AM29_FNNAME(am29_hw_erase) ); + + AM29_INTSCACHE_BEGIN(); + result = (*erase_fn)(block); + AM29_INTSCACHE_END(); + + // The erase may have failed for a number of reasons, e.g. because + // of a locked sector. The best thing to do here is to check that the + // erase has succeeded. + block = (AM29_TYPE*) addr; + for (i = 0; i < (block_size / sizeof(AM29_TYPE)); i++) { + if (block[i] != (AM29_TYPE)~0) { + // There is no easy way of detecting the specific error, + // e.g. locked flash block, timeout, ... So return a + // useless catch-all error. + return CYG_FLASH_ERR_ERASE; + } + } + return CYG_FLASH_ERR_OK; +} + +// Write some data to the flash. The destination must be aligned +// appropriately for the bus width (not the device width). +int +AM29_FNNAME(cyg_am29xxxxx_program)(struct cyg_flash_dev* dev, cyg_flashaddr_t dest, const void* src, size_t len) +{ + int (*program_fn)(volatile AM29_TYPE*, volatile AM29_TYPE*, const cyg_uint8*, cyg_uint32, int); + volatile AM29_TYPE* block; + volatile AM29_TYPE* addr; + cyg_flashaddr_t block_start; + size_t block_size; + const cyg_uint8* data; + int retries; + int i; + + AM29_INTSCACHE_STATE; + + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + + amd_diag("dest %p src %p len %d\n", (void*)dest, (void*)src, (int)len ); + + // Only support writes that are aligned to the bus boundary. This + // may be more restrictive than what the hardware is capable of. + // However it ensures that the hw_program routine can write as + // much data as possible each iteration, and hence significantly + // improves performance. The length had better be a multiple of + // the bus width as well + if ((0 != ((CYG_ADDRWORD)dest & (sizeof(AM29_TYPE) - 1))) || + (0 != (len & (sizeof(AM29_TYPE) - 1)))) { + return CYG_FLASH_ERR_INVALID; + } + + addr = AM29_UNCACHED_ADDRESS(dest); + CYG_ASSERT((dest >= dev->start) && (dest <= dev->end), "flash address out of device range"); + + am29_get_block_info(dev, dest, &block_start, &block_size); + CYG_ASSERT(((dest - block_start) + len) <= block_size, "write cannot cross block boundary"); + + block = AM29_UNCACHED_ADDRESS(block_start); + data = (const cyg_uint8*) src; + retries = CYGNUM_DEVS_FLASH_AMD_AM29XXXXX_V2_PROGRAM_TIMEOUT; + + program_fn = (int (*)(volatile AM29_TYPE*, volatile AM29_TYPE*, const cyg_uint8*, cyg_uint32, int)) + cyg_flash_anonymizer( & AM29_FNNAME(am29_hw_program) ); + + AM29_INTSCACHE_BEGIN(); + (*program_fn)(block, addr, data, len / sizeof(AM29_TYPE), retries); + AM29_INTSCACHE_END(); + + // Too many things can go wrong when manipulating the h/w, so + // verify the operation by actually checking the data. + addr = (volatile AM29_TYPE*) dest; + data = (const cyg_uint8*) src; + for (i = 0; i < (len / sizeof(AM29_TYPE)); i++) { + AM29_TYPE datum = AM29_NEXT_DATUM(data); + AM29_TYPE current = addr[i]; + if ((datum & current) != current) { + amd_diag("data %p addr[i] %p datum %08x current %08x\n", data-sizeof(AM29_TYPE), &addr[i], datum, current ); + return CYG_FLASH_ERR_PROGRAM; + } + } + return CYG_FLASH_ERR_OK; +} + +int +AM29_FNNAME(cyg_at49xxxx_softlock)(struct cyg_flash_dev* dev, const cyg_flashaddr_t dest) +{ + volatile AM29_TYPE* uncached; + int result; + int (*lock_fn)(volatile AM29_TYPE*); + AM29_INTSCACHE_STATE; + + amd_diag("\n"); + + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + CYG_ASSERT((dest >= (cyg_flashaddr_t)dev->start) && + ((CYG_ADDRESS)dest <= dev->end), "flash address out of device range"); + + uncached = AM29_UNCACHED_ADDRESS(dest); + lock_fn = (int (*)(volatile AM29_TYPE*)) cyg_flash_anonymizer( & AM29_FNNAME(at49_hw_softlock) ); + AM29_INTSCACHE_BEGIN(); + result = (*lock_fn)(uncached); + AM29_INTSCACHE_END(); + return result; +} + +int +AM29_FNNAME(cyg_at49xxxx_hardlock)(struct cyg_flash_dev* dev, const cyg_flashaddr_t dest) +{ + volatile AM29_TYPE* uncached; + int result; + int (*lock_fn)(volatile AM29_TYPE*); + AM29_INTSCACHE_STATE; + + amd_diag("\n"); + + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + CYG_ASSERT((dest >= (cyg_flashaddr_t)dev->start) && + ((CYG_ADDRESS)dest <= dev->end), "flash address out of device range"); + + uncached = AM29_UNCACHED_ADDRESS(dest); + lock_fn = (int (*)(volatile AM29_TYPE*)) cyg_flash_anonymizer( & AM29_FNNAME(at49_hw_hardlock) ); + AM29_INTSCACHE_BEGIN(); + result = (*lock_fn)(uncached); + AM29_INTSCACHE_END(); + return result; +} + +int +AM29_FNNAME(cyg_at49xxxx_unlock)(struct cyg_flash_dev* dev, const cyg_flashaddr_t dest) +{ + volatile AM29_TYPE* uncached; + int result; + int (*unlock_fn)(volatile AM29_TYPE*); + AM29_INTSCACHE_STATE; + + amd_diag("\n"); + + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + CYG_ASSERT((dest >= (cyg_flashaddr_t)dev->start) && + ((CYG_ADDRESS)dest <= dev->end), "flash address out of device range"); + + uncached = AM29_UNCACHED_ADDRESS(dest); + unlock_fn = (int (*)(volatile AM29_TYPE*)) cyg_flash_anonymizer( & AM29_FNNAME(at49_hw_unlock) ); + + AM29_INTSCACHE_BEGIN(); + result = (*unlock_fn)(uncached); + AM29_INTSCACHE_END(); + return result; +} + +// ---------------------------------------------------------------------------- +// Clean up the various #define's so this file can be #include'd again +#undef AM29_FNNAME +#undef AM29_RAMFNDECL +#undef AM29_OFFSET_COMMAND +#undef AM29_OFFSET_COMMAND2 +#undef AM29_OFFSET_DEVID +#undef AM29_OFFSET_DEVID2 +#undef AM29_OFFSET_DEVID3 +#undef AM29_OFFSET_CFI +#undef AM29_OFFSET_CFI_DATA +#undef AM29_OFFSET_AT49_LOCK_STATUS +#undef AM29_PARALLEL |