Index: packages/devs/flash/intel/stratav2/current/ChangeLog =================================================================== RCS file: packages/devs/flash/intel/stratav2/current/ChangeLog diff -N packages/devs/flash/intel/stratav2/current/ChangeLog --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/intel/stratav2/current/ChangeLog 18 Nov 2008 01:01:18 -0000 @@ -0,0 +1,496 @@ +2008-11-13 Jonathan Larmour + + * include/flash_strata_v2.inl: + * include/strata_v2_priv.h: + Remove these as they are now unused and don't match the CDL. + +2006-08-08 Jonathan Larmour + + * src/strata.c: Provide a default HAL_MEMORY_BARRIER() + define if the HAL hasn't provided one. + * src/strata_aux.c: Use HAL_MEMORY_BARRIER() any time the + flash is switched back to read array mode. Some processors need + to have their write buffers flushed. + +2006-08-02 Jonathan Larmour + + * include/strata_dev.h: Replace use of flash_priv.h by flash_dev.h + as per io/flash changes. + * src/strata.c: Ditto. + +2006-07-31 Jonathan Larmour + + * src/strata.c: Remove strata-specific nop devfn functions now + provided by io/flash. Also strata_anonymizer. + * src/strata_aux.c: Change strata_anonymizer to cyg_flash_anonymizer. + + * doc/strata.sgml: Update to reflect generic nop devfn functions + now provided by io/flash. + +2006-05-15 John Dallaway + + * cdl/flash_strata_v2.cdl: Add reference to package documentation. + +2006-04-09 Bart Veer + + * src/strata_aux.c (strata_hw_bufprogram): re-read status after + the loop, the bits may not all change at the same time. + +2006-03-31 Jonathan Larmour + + * src/strata_aux.c (strata_hw_erase): Workaround for + ST M58XXXX doesn't work for parallel flash. Another + hack put in place instead so it works not just for + parallel flash in general, but also parallel ST M58XXXX + should that ever be used in future. + (strata_hw_bufprogram): count of bytes to write has to + be STRATA_PARALLELed to affect all parallel devices. + +2006-03-29 Nick Garnett + + * src/strata_aux.c (cyg_strata_program): Fixed bug in + increments/decrements during main loop to match those in + bufprogram. + Modified diagnostic output a little. + +2006-01-24 Jonathan Larmour + + * src/strata.c (STRATA_OFFSET_CFI_WRITE_BUFFER_LSB): Add definition + of CFI offset. Ditto _MSB. + + * src/strata_aux.c (strata_hw_cfi): Detect writebuffer size. + +2005-11-28 Nick Garnett + + * src/strata_aux.c: Added support for byte swapping the command + and status reads and writes. Fixed some pointer increment bugs. + Added some diagnostic macros. + + * src/strata.c: Added byte swapping support. + +2005-08-03 Jonathan Larmour +2005-08-03 Bart Veer + + * src/strata.c (STRATA_INTSCACHE_DEFAULT_END): In the + case of !defined(CYGHWR_DEVS_FLASH_STRATA_V2_CACHED_ONLY) and + !defined(CYGIMP_DEVS_FLASH_STRATA_V2_LEAVE_INTERRUPTS_ENABLED) + briefly blip the interrupt enable on to allow pending interrupts + to run, thus reducing max interrupt latency. + +2005-08-02 Jonathan Larmour + + * src/strata.c (STRATA_INTSCACHE_DEFAULT_END): Even when + !defined(CYGHWR_DEVS_FLASH_STRATA_V2_CACHED_ONLY) we need to + remove stale dcache entries for the Flash before finishing + the whole operation. So invalidate (and therefore also sync) + the dcache. + + * src/strata_aux.c (cyg_strata_lock_j3): Allow building with + assertions enabled (CYGPKG_INFRA_DEBUG). + (cyg_strata_unlock_all_j3): Ditto. + (cyg_strata_lock_k3): Ditto. + (cyg_strata_unlock_k3): Ditto. + +2005-07-25 Bart Veer + + * cdl/flash_strata_v2.cdl: add configury for finer control of the + cache and interrupts. + * src/strata.c: STRATA_P2V() renamed to STRATA_UNCACHED_ADDRESS(), + a more appropriate name. Provide three versions of the INTSCACHE() + macros for different configurations. + * src/strata_aux.c: use STRATA_UNCACHED_ADDRESS() throughout. + Sort out the assertions properly. Reorganize status bit checks + and add comment re. discrepancy with datasheets. + * include/strata_dev.h, src_strata_aux.c: unlock_all_j3 now takes + a cyg_flashaddr_t instead of a device pointer, for compatibility + with the main flash API. + +2005-06-16 Jonathan Larmour + + * src/strata_aux.c (strata_hw_erase): Order detection of errors + correctly, so most appropriate error codes get returned first. + (strata_hw_program): Ditto. + (strata_hw_bufprogram): Ditto. + (strata_hw_lock_j3): Ditto. Also remove duplicate resetting to + read array. + (strata_hw_unlock_all_j3): Ditto. + (cyg_strata_program): Place assertion check correctly. + (cyg_strata_bufprogram): Ditto. + (cyg_strata_lock_j3): Ditto. + (cyg_strata_lock_k3): Ditto. + (cyg_strata_unlock_k3): Ditto. + +2005-06-16 Bart Veer + + * src/strata_aux.c (strata_hw_bufprogram): Write the correct + number of bytes. Confirm write at correct address. + (cyg_strata_bufprogram): update "written" correctly. + +2005-06-11 Bart Veer + + * cdl/flash_strata_v2.cdl, include/strata_dev.h, src/strata.c, + src/strata_aux.c, doc/strata.sgml: new version of the V2 strata + driver based on the am29xxxxxv2 driver, interrupt and cache safe. + +2004-11-29 Bart Veer + + * include/flash_strata_v2.inl: hwr_map_error() is now internal to + the driver, not exported to the generic flash code. + + * include/flash_strata_v2.inl: use the dummy lock/unlock functions + provided by the generic flash code. + +2004-11-25 Andrew Lunn + + * include/flash_strata_v2.inl: Correct the usage of const + parameters. strata_init() needs to be able to modify priv. + strata_program_buf() does not need to modify priv. + +2004-11-25 Bart Veer + + * cdl/flash_strata_v2.cdl: this V2 driver relies on the generic + flash code to handle the cache + +2004-11-22 Bart Veer + + * include/flash_strata_v2.inl: adjust const parameters as per + change to generic flash package + * include/flash_strata_v2.inl: rename cyg_block_info to + cyg_flash_block_info + +2004-11-21 Bart Veer + + * cdl/flash_strata_v2.cdl: CYGHWR_IO_FLASH_DEVICE_V2 is now + implicit + +2004-09-14 Andrew Lunn + + * include/flash_strata_v2.inl: Return the end address which is the + last valid address, not the first invalid address. + Also import Mark Salters changes from the trunk. + +2004-08-21 Andrew Lunn + + * include/flash_strata_v2.inl (flash_unlock_block): + * cdl/flash_strata_v2.cdl: CDL to control the maximum number of + blocks the driver supports. Some of the newer strata device has more + than the default maximum of 128. Problem pointed out by Kevin Zhang. + +2004-08-13 Andrew Lunn + + * cdl/flash_strata_v2.cdl: Indicate we implement + CYGHWR_IO_FLASH_BLOCK_LOCKING when + CYGOPT_DEVS_FLASH_STRATA_V2_LOCKING is enabled. + * include/flash_strata_v2.inl: Make block unlock and + lock compile. + +2004-08-05 Andrew Lunn + + * New version of the strata driver based on the old version. This + version uses the new flash device API. + +2005-01-26 Scott Wilkinson + * src/strata.h: + * src/strata.c: + Flash from STMicro is compatible with the Intel strata chips, + so detect them as well. Check for manuf id 0x20. + +2003-10-29 Jonathan Larmour + + * src/flash_unlock_block.c (flash_unlock_block): test lock bit + explicitly - newer flash parts use the reserved bits in the + returned data. + +2003-09-11 Jani Monoses + + * src/flash_erase_block.c (flash_erase_block): + * src/flash_program_buf.c (flash_program_buf): Fix bootblock handling + in erase. Fix erase and word-program for Synchronous Strata and later + chips where block address and word address are required in the first + cycle of the operation while for earlier parts any address was good. + +2003-09-10 Jani Monoses + + * cdl/flash_strata.cdl: + * src/flash_lock_block.c (flash_lock_block): + * src/flash_unlock_block.c (flash_unlock_block): + * src/flash_erase_block.c (flash_erase_block): + * src/flash_query.c (flash_query): + * src/flash_program_buf.c (flash_program_buf): Use .2ram sections + for putting flash functions to RAM instead of the old method. + +2003-05-02 Jani Monoses + + * src/strata.c: Switch to using generic flash_query_dev. + The previous cache related changes broke flash_query for + Strata because in the query case the generic flash driver was not + called to handle the caches but the internal handling was removed + nevertheless. + +2003-04-04 Jani Monoses + + * src/strata.h: + Use generic flash_dev.h for providing the FLASHWORD macro for + different widths and device numbers.No reason to duplicate that + here.This implicitely fixes the case when CYGNUM_FLASH_WIDTH is 16 + and CYGNUM_FLASH_DEVICES is 4. + +2003-04-03 Jani Monoses + + * src/flash_lock_block.c (flash_lock_block): + * src/flash_unlock_block.c (flash_unlock_block): + * src/flash_erase_block.c (flash_erase_block): + * src/flash_query.c (flash_query): + * src/flash_program_buf.c (flash_program_buf): + Cache enabling and disabling are already handled by generic flash + +2002-08-12 Mark Salter + + * src/flash_unlock_block.c: Add synchronous strataflash support. + * src/strata.h: Add comments regarding synchronous strataflash. + +2002-04-30 Christoph Csebits + + * src/flash_unlock_block.c: Getting the current block lock + state for flashes in 8-Bit mode is now working correctly. + +2002-04-16 Jonathan Larmour + + * cdl/flash_strata.cdl: Invoke $(CC) with $(CFLAGS) to ensure the + correct flags are passed. + +2002-04-12 Gary Thomas + + * src/strata.c: Clean up warnings. + +2002-01-22 Mark Salter + + * cdl/flash_strata.cdl: Add ".text" before "_end" markers in .s files. + +2001-10-23 Hugo Tyson + + * cdl/flash_strata.cdl: Provide an option so that RedBoot .ecm + files can turn off the functionality of copying flash driver code + to separate RAM for execution; it's not needed for RAM and ROMRAM + startup, and for some platforms it is required to *not* copy thus. + +2001-08-25 Gary Thomas + + * src/flash_program_buf.c (flash_program_buf): Allow configuration + specific code sequence for actual writing of data. Define by the + macro CYGHWR_FLASH_WRITE_ELEM. Note: this is required on some + hardware, like the Intel SA185, which handles flash writes in + strange/obscure fashion. + +2001-07-17 Jeroen Dobbelaere + + * src/flash_query.c (flash_query): Query needs to be done on even + addresses for byte-enabled strata flash + + * src/flash_program_buf.c (flash_program_buf): Fix of conversion of + write buffer length (in bytes) to the length in 'flash_t' words. + +2001-06-22 Hugo Tyson + + * src/strata.c (flash_hwr_init): Need to refer to the query code + as extern char flash_query[], flash_query_end[]; (with the []) or + MIPS code gen assumes these are short offsets and linking fails. + The generic flash code in io/flash already uses this idiom. + +2001-06-22 Hugo Tyson + + * src/strata.c (flash_hwr_init): Warnings reduced. No arithmetic + on void *. + +2001-06-21 Hugo Tyson + + * src/flash_program_buf.c (flash_program_buf): The buffered write + code didn't jump out if there was a write error, nor verify the + data by reading back. This isn't consistent with the slow case, + and made it take an age if the device is unhappy, and then report + a bizarre error code. Both issues fixed. + +2001-06-21 Hugo Tyson + + * src/strata.c (flash_hwr_init): If shrinking to fit, must also + adjust the flash_info.blocks field, else unlock crashes trying to + get status of all those extra blocks that we cannot actually see. + +2001-06-11 Gary Thomas + + * src/strata.c: Remove dependency on printf() via user functions. + +2001-06-07 Hugo Tyson + + * src/strata.c (flash_hwr_init): If we find a flash device that is + larger than is possible given the memory map, shrink to fit. + We know about the memory map from CYGNUM_FLASH_BASE_MASK (if + defined); it tells us the stride from one device to another. + + This is to cope with installing, say, a 28F640 in a slot designed + for a 28F320 because of supply issues - it all works fine so long + as A22 is grounded. + +2001-05-23 Jesper Skov + + * cdl/flash_strata.cdl: Needs IO driver to copy functions to RAM. + +2001-04-26 Gary Thomas + + * src/strata.c: Be more careful when enable/flush/disable caches. + + * src/flash_erase_block.c (flash_erase_block): Boot block devices + may require additional erase commands to erase entire 'block'. + +2001-03-21 Hugo Tyson + + * src/strata.h (FLASH_Write_Buffer): Do not define this if + CYGOPT_FLASH_IS_NOT_ADVANCED is defined; Advanced (xxxJ3) flash is + usual these days. Also added documentation of the options that + can be used to control this module. + + * src/flash_program_buf.c (flash_program_buf): Reduce warnings + about unused variables if no FLASH_Write_Buffer command available. + +2001-03-21 Gary Thomas + + * src/flash_program_buf.c (flash_program_buf): Buffered write code + fixups, only on platforms with it defined. + +2001-03-17 Gary Thomas + + * src/strata.h: + * src/strata.c: Support buffered writes. + + * src/flash_program_buf.c: Use buffered writes if possible. This + mode allows the chip to do parallelized writes which is much faster. + It does require additional information, now provided by upper layer. + +2001-02-15 Hugo Tyson + + * src/flash_query.c (flash_query): Depending on whether + CYGOPT_FLASH_IS_BOOTBLOCK (just a #define from the instantiator, + not really a cdl_option) is set, do the full Read_Query or just + acquire two codes for manufacturer and device type using Read_ID. + + * src/strata.c (flash_hwr_init): Again depending on whether + CYGOPT_FLASH_IS_BOOTBLOCK, decode the device type into a size and + so on, or use the full Read_Query data as before. + + * src/strata.h (FLASH_Read_ID): Undefine those commands which we + do not use. Conditionally define those that we use depending on + CYGOPT_FLASH_IS_BOOTBLOCK. Thus we should be able to deal with + StrataFlash and BootBlock flash with the same code. + + * cdl/flash_strata.cdl: Do not implement (in the CDL sense) + CYGHWR_IO_FLASH_BLOCK_LOCKING leave it up to the instantiating + package instead. Also move the build of the two objects that do + locking and unlocking into a compenent which is only active if + CYGHWR_IO_FLASH_BLOCK_LOCKING is indeed (requested to be) + implemented somewhere. + +2001-02-14 Hugo Tyson + + * devs/flash/intel/strata/...: New package, generic strataFlash + driver based on several others; a portion of its history + follows... + + flash.h -> strata.h + flash.c -> strata.c + +2001-02-06 Hugo Tyson + + * src/flash.h: Much more generic again. Not yet separated into + generic component and invocation header, but the structure is + there. Also included support for a mapping from the physical + flash address we're thinking of to the virtual address we use to + access it. More documentation. Generalization to 8,16,32 and + 64-bit access, made up from 8,16 or 32-bit devices. Command and + status macros modified to accommodate these options. + + * src/flash_lock_block.c (flash_lock_block): + * src/flash_erase_block.c (flash_erase_block): + * src/flash_query.c (flash_query): + * src/flash_program_buf.c (flash_program_buf): + All now acquire when possible the ROM address from the block + address, and use the physical to virtual macro as needed. + + * src/flash_unlock_block.c (flash_unlock_block): + The same changes, but a little more complex because of the need to + clear-all then re-lock some semantics. Shadow pointer to virtual + address is used each time round the loop. + + * cdl/flash_strata.cdl: Add explicit dependencies on flash.h, for + there were none - or they were ignored - for the specially built + compilation units that get copied to RAM for execution. + +2001-02-01 Hugo Tyson + + * all: copied from the assabet flash driver. + +2000-12-05 Jonathan Larmour + + * src/assabet_flash.c (flash_code_overlaps): Define stext/etext + as array types so no assumptions can be made by the compiler about + location. + +2000-10-24 Gary Thomas + + * src/flash_unlock_block.c (flash_unlock_block): + * src/flash_lock_block.c (flash_lock_block): + * src/flash_program_buf.c (flash_program_buf): + * src/flash_erase_block.c (flash_erase_block): Support up to 32M FLASH. + +2000-09-10 Gary Thomas + + * src/flash_unlock_block.c: + * src/flash_lock_block.c: New file(s). + + * src/flash.h: + * cdl/flash_assabet.cdl: Add region locking functions. + +2000-08-29 Gary Thomas + + * src/assabet_flash.c: Improve error decoding. + +2000-08-24 Gary Thomas + + * src/flash_query.c: + * src/flash_erase_block.c: + * src/flash.h: FLASH support for Intel SA1110 Assabet. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2004, 2005, 2006 eCosCentric Limited +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== Index: packages/devs/flash/intel/stratav2/current/cdl/flash_strata_v2.cdl =================================================================== RCS file: packages/devs/flash/intel/stratav2/current/cdl/flash_strata_v2.cdl diff -N packages/devs/flash/intel/stratav2/current/cdl/flash_strata_v2.cdl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/intel/stratav2/current/cdl/flash_strata_v2.cdl 18 Nov 2008 01:01:18 -0000 @@ -0,0 +1,209 @@ +# ==================================================================== +# +# flash_strata_v2.cdl +# +# FLASH memory - Hardware support for Intel Strata Flash +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 2004, 2005, 2006 eCosCentric Limited +## +## 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., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): bartv +# Contributors: +# Date: 2005-06-11 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_STRATA_V2 { + display "Intel StrataFLASH memory support" + doc ecospro-ref/devs-flash-strata.html + parent CYGPKG_IO_FLASH + active_if CYGPKG_IO_FLASH + implements CYGHWR_IO_FLASH_DEVICE + include_dir cyg/io + compile strata.c + + description " + Flash memory support for Intel StrataFlash devices and compatibles. + This driver implements the V2 flash driver API" + + cdl_option CYGNUM_DEVS_FLASH_STRATA_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_STRATA_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_STRATA_V2_LEAVE_INTERRUPTS_ENABLED { + display "Leave interrupts enabled during flash operations" + active_if { ! CYGHWR_DEVS_FLASH_STRATA_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_STRATA_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_option CYGNUM_DEVS_FLASH_STRATA_V2_ERASE_REGIONS { + display "Number of different erase regions" + flavor data + default_value 2 + 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 eight 8K blocks, followed by 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 two 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_option CYGNUM_DEVS_FLASH_STRATA_V2_BLOCKS { + display "Maximum number of blocks per device" + flavor data + default_value 256 + legal_values 1 to 65536 + description " + The unlock operation on some members of the Strata family of flash chips, + for example the j3 series, is complicated. There is no individual block + unlock command, only a global unlock. Hence to unlock a single block it + is necessary to read the current locked state of all blocks, unlock all + blocks, then restore the locked state where appropriate. This requires + one bit on the stack for every block, so the maximum number of blocks + must be known at compile-time. The default value of 256 should suffice + for most flash devices and results in additional stack usage of 32 bytes, + small enough that it should not cause stack overflow problems. The + platform HAL may require a larger value if the board's flash chips + require it." + } + + cdl_component CYGPKG_DEVS_FLASH_STRATA_V2_OPTIONS { + display "Strata driver build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building the Strata + flash driver, and details of which tests are built." + + cdl_option CYGPKG_DEVS_FLASH_STRATA_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 Strata flash driver. These flags + are used in addition to the set of global flags." + } + + cdl_option CYGPKG_DEVS_FLASH_STRATA_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 Strata flash driver. These flags + are removed from the set of global flags if present." + } + } +} + Index: packages/devs/flash/intel/stratav2/current/doc/strata.sgml =================================================================== RCS file: packages/devs/flash/intel/stratav2/current/doc/strata.sgml diff -N packages/devs/flash/intel/stratav2/current/doc/strata.sgml --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/intel/stratav2/current/doc/strata.sgml 18 Nov 2008 01:01:18 -0000 @@ -0,0 +1,916 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Intel Strata Flash Device Driver + + + + Overview + + + Overview + eCos Support for Intel Strata Flash Devices and Compatibles + + + Description + +The CYGPKG_DEVS_FLASH_STRATA_V2 +flash driver package implements support for the Intel Strata +family of flash devices and compatibles. The driver is not normally +accessed directly. Instead application code will use the API provided +by the generic flash driver package +CYGPKG_IO_FLASH, for example by calling functions +like cyg_flash_program. There are a small number +of additional functions +specific to Strata devices. + + +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. + + +Many eCos targets with Strata or compatible flash devices will +still use the older driver package +CYGPKG_DEVS_FLASH_STRATA. Only newer ports +and some older ports that have been converted will use the V2 driver. +This documentation only applies to the V2 driver. + + + + Configuration Options + +The Strata 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 +CYGPKG_IO_FLASH 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 Strata driver package. + + +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 +CYGNUM_DEVS_FLASH_STRATA_V2_ERASE_REGIONS 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. + + + + + + + Instantiating a Strata Device + + + Instantiating + including the driver in an eCos target + + + + +#include <cyg/io/strata_dev.h> + + + int cyg_strata_init_nop + struct cyg_flash_dev* device + + + int cyg_strata_init_check_devid_XX + struct cyg_flash_dev* device + + + int cyg_strata_init_cfi_XX + struct cyg_flash_dev* device + + + int cyg_strata_erase_XX + struct cyg_flash_dev* device + cyg_flashaddr_t addr + + + int cyg_strata_program_XX + struct cyg_flash_dev* device + cyg_flashaddr_t addr + const void* data + size_t len + + + int cyg_strata_bufprogram_XX + struct cyg_flash_dev* device + cyg_flashaddr_t addr + const void* data + size_t len + + + int cyg_strata_lock_j3_XX + struct cyg_flash_dev* device + const cyg_flashaddr_t addr + + + int cyg_strata_unlock_j3_XX + struct cyg_flash_dev* device + const cyg_flashaddr_t addr + + + int cyg_strata_lock_k3_XX + struct cyg_flash_dev* device + const cyg_flashaddr_t addr + + + int cyg_strata_unlock_k3_XX + struct cyg_flash_dev* device + const cyg_flashaddr_t addr + + + + + Description + +The Strata family contains a number of different devices, all +supporting the same basic set of operations but with various common or +uncommon extensions. The range includes: + + + + 28FxxxB3 Boot Block + +These support 8 8K boot blocks as well as the usual 64K blocks. There +is no buffered write capability. The only locking mechanism available +involves manipulating voltages on certain pins. + + + + 28FxxxC3 + +These also have boot blocks. There is no buffered write capability. +Individual blocks can be locked and unlocked in software. + + + + 28FxxxJ3 + +These are uniform devices where all blocks are 128K. Buffered writes +are supported. Blocks can be locked individually, but the only unlock +operation is a global unlock-all. + + + + 28FxxxK3 + +These are also uniform devices with 128K blocks. Buffered writes are +supported. Individual blocks can be locked and unlocked in software. + + + + +Each of these comes in a range of sizes and bus widths. 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 +Strata driver package cannot know all this information. Instead it +is the responsibility of another package, usually the platform HAL, to +instantiate some flash device structures. Two pieces of information +are especially important: the bus configuration and the boot block +layout. + + +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 usually there will be a trade off between cost and performance. +For example two 16-bit devices in parallel can provide twice the +memory bandwidth of a single device. The driver supports the following +combinations: + + + + 8 + +A single 8-bit flash device on an 8-bit bus. + + + + 16 + +A single 16-bit flash device on a 16-bit bus. + + + + 32 + +A single 32-bit flash device on an 32-bit bus. + + + + 88 + +Two parallel 8-bit devices on an 16-bit bus. + + + + 8888 + +Four parallel 8-bit devices on a 32-bit bus. + + + + 1616 + +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 upper two bytes. + + + + 16as8 + +A single 16-bit flash device connected to an 8-bit bus. + + + + +These configuration all require slightly different code to manipulate +the hardware. The Strata driver package provides separate functions +for each configuration, for example +cyg_strata_erase_16 and +cyg_strata_program_1616. + + +At the time of writing not all the configurations have been tested. + + +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 some flash devices also support a number of +smaller boot blocks. A typical 2MB flash device could have eight 8K +blocks and 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. + + + + Example + +Flash support is usually specific to each 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 is generally 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: + + +cdl_package CYGPKG_HAL_M68K_KIKOO { + … + compile -library=libextras.a kikoo_flash.c + … +} + + +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 libextras.a. + + +The actual file kikoo_flash.c will look something like: + + +#include <pkgconf/system.h> +#ifdef CYGPKG_DEVS_FLASH_STRATA_V2 + +#include <cyg/io/flash.h> +#include <cyg/io/strata_dev.h> + +static const CYG_FLASH_FUNS(hal_kikoo_flash_strata_funs, + &cyg_strata_init_check_devid_16, + &cyg_flash_devfn_query_nop, + &cyg_strata_erase_16, + &cyg_strata_bufprogram_16, + (int (*)(struct cyg_flash_dev*, const cyg_flashaddr_t, void*, size_t))0, + &cyg_strata_lock_j3_16, + &cyg_strata_unlock_j3_16); + +static const cyg_strata_dev hal_kikoo_flash_priv = { + .manufacturer_code = CYG_FLASH_STRATA_MANUFACTURER_INTEL, + .device_code = 0x0017, + .bufsize = 16, + .block_info = { + { 0x00020000, 64 } // 64 * 128K blocks + } +}; + +CYG_FLASH_DRIVER(hal_kikoo_flash, + &hal_kikoo_flash_amd_funs, + 0, + 0x60000000, + 0x601FFFFF, + 1, + hal_kikoo_flash_priv.block_info, + &hal_kikoo_flash_priv +); +#endif + + +The bulk of the file is protected by an ifdef for the Strata 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 there is no point in instantiating the device. The rest +of the file is split into three 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 cyg/io/flash_dev.h. The +relevant ones have an _16 suffix, indicating that +on this board there is a single 16-bit flash device on a 16-bit +bus. The second definition provides information specific to Strata +flash devices. The third provides the +cyg_flash_dev structure needed by the generic +flash code, which contains pointers to the previous two. + + + + Functions + +All eCos flash device drivers must implement a standard interface, +defined by the generic flash code CYGPKG_IO_FLASH. +This interface includes a table of 7 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 +cyg_flash_devfn_query_nop. Strata flash devices +are always directly accessible so there is no need for a separate read +function. The remaining functions are more complicated. + + +Usually the table can be declared const. In a ROM +startup application this avoids both ROM and RAM copies of the table, +saving a small amount of memory. const should not +be used if the table may be modified by a platform-specific +initialization routine. + + + Initialization + +There is a choice of three main initialization functions. The simplest +is cyg_flash_devfn_init_nop, which does nothing. It +can be used if the cyg_strata_dev and +cyg_flash_dev 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. + + +The next step up is +cyg_strata_init_check_devid_XX, where +XX will be replaced by the suffix appropriate for +the bus configuration. It is still necessary to provide all the device +information statically, including the devid +field in the cyg_strata_dev structure. +However this initialization function will attempt to query the flash +device and check that the provided manufacturer and device codes +matches the actual hardware. If there is a mismatch the device will be +marked uninitialized and subsequent attempts to manipulate the flash +will fail. + + +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 cyg_strata_init_cfi_XX +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 +block_info field in the +cyg_strata_dev structure and the +end and +num_block_infos fields in the +cyg_flash_dev structure will be filled in. +It is still necessary to supply the start +field statically since otherwise the driver will not know how to +access the flash device. The main disadvantage of using CFI is that it +will increase the code size. + + +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 Strata driver provides a utility function to +read the device id, cyg_strata_read_devid_XX: + + +static int +kikoo_flash_init(struct cyg_flash_dev* dev) +{ + int manufacturer_code, device_code; + cyg_strata_read_devid_1616(dev, &manufacturer_code, &device_code); + if (manufacturer_code != CYG_FLASH_STRATA_MANUFACTURER_STMICRO) { + return CYG_FLASH_ERR_DRV_WRONG_PART; + } + switch(device_code) { + case 0x0042 : + … + case 0x0084 : + … + default: + return CYG_FLASH_ERR_DRV_WRONG_PART; + } +} + + +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 was fixed in the next revision. The +platform-specific initialization function could figure out which model +board it is running on and replace the default +16as8 functions with 16 ones. + + + + Erase and Program + +The Strata 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. For +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: + + +static int +kikoo_flash_erase(struct cyg_flash_dev* dev, cyg_flashaddr_t addr) +{ + int result; + … // Set up the hardware for an erase + result = cyg_strata_erase_32(dev, addr); + … // Revert the hardware change + return result; +} + + +There are two versions of the program function. +cyg_strata_bufprogram_xx uses the buffered write +capability of some strata chips. This allows the flash chip to perform +the writes in parallel, thus greatly improving performance. It +requires that the bufsize field of the +cyg_strata_dev structure is set correctly to +the number of words in the write buffer. The usual value for this is +16, corresponding to a 32-byte write buffer. The alternative +cyg_strata_program_xx writes the data one word at +a time so is significantly slower. It should be used only with strata +chips that do not support buffered writes, for example the b3 and c3 +series. + + +There are two configuration options which affect the erase and program +functions, and which a platform HAL may wish to change: +CYGNUM_DEVS_FLASH_STRATA_V2_ERASE_TIMEOUT and +CYGNUM_DEVS_FLASH_STRATA_V2_PROGRAM_TIMEOUT. 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, and hence a timeout probably 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. + + + + Locking + +Current Strata devices implement locking in three different ways, +requiring different sets of functions: + + + + 28FxxxB3 + +There is no software locking support. The +cyg_flash_devfn_lock_nop and +cyg_flash_devfn_unlock_nop functions should be used. + + + + 28FxxxC3 + 28FxxxK3 + +These support locking and unlocking individual blocks. The +cyg_strata_lock_k3_XX and +cyg_strata_unlock_k3_XX functions should be used. +All blocks are locked following power-up or reset, so the unlock +function must be used before any erase or program operation. +Theoretically the lock function is optional and +cyg_flash_devfn_lock_nop can be used instead, saving a +small amount of code space. + + + + 28FxxxJ3 + +Individual blocks can be locked using +cyg_strata_lock_j3_XX, albeit using a slightly +different algorithm from the C3 and K3 series. However the only unlock +support is a global unlock of all blocks. Hence the only way to unlock +a single block is to check the locked status of every block, unlock +them all, and relock the ones that should still be locked. This +time-consuming operation is implemented by +cyg_strata_unlock_j3_XX. Worse, unlocking all +blocks can take approximately a second. During this time the flash is +unusable so normally interrupts have to be disabled, affecting +real-time responsiveness. There is no way of suspending this +operation. + + +Unlike the C3 and K3 chips, on a J3 blocks are not automatically +locked following power-up or reset. Hence lock and unlock support is +optional, and cyg_flash_devfn_lock_nop and +cyg_flash_devfn_unlock_nop can be used. + + + + +If real locking functions are used then the platform HAL's CDL script +should implement the CDL interface +CYGHWR_IO_FLASH_BLOCK_LOCKING. Otherwise the +generic flash package may believe that none of the flash drivers in +the system provide locking functionality and disable the interface +functions. + + + + + Device-Specific Structure + +The cyg_strata_dev structure provides +information specific to Strata flash devices, as opposed to the +more generic flash information which goes into the +cyg_flash_dev structure. There are only two +fields: devid and +block_info. + + +manufacturer_code and +device_code are needed only if the driver's +initialization function is set to +cyg_strata_init_check_devid_XX. That function +will extract the actual device info from the flash chip and compare it +with these fields. If there is a mismatch then subsequent operations +on the device will fail. Definitions of +CYG_FLASH_STRATA_MANUFACTURER_INTEL and +CYG_FLASH_STRATA_MANUFACTURER_STMICRO are provided +for convenience. + + +The bufsize field is needed only if a +buffered program function +cyg_strata_bufprogram_XX is used. It should give +the size of the buffer in words. Typically Strata devices have a +32-byte buffer, so when attached to an 8-bit bus +bufsize should be 32 and when attached to a +16-bit bus it should be 16. + + +The block_info 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: + + + +If the driver initialization function is set to +cyg_strata_init_nop or +cyg_strata_init_check_devid_XX then the block +information should be provided statically. This is appropriate if the +board will also be manufactured using the same flash chip. + + +If cyg_strata_init_cfi_XX is used then this +will fill in the block info table. Hence there is no need for static +initialization. + + +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. + + + +The size of the block_info table is +determined by the configuration option +CYGNUM_DEVS_FLASH_STRATA_V2_ERASE_REGIONS. +This has a default value of 2, which should suffice for nearly all +Strata flash devices. If more entries are needed then the platform +HAL's CDL script should require a larger value. + + +If the cyg_strata_dev structure is +statically initialized then it can be const. This +saves a small amount of memory in ROM startup applications. If the +structure may be updated at run-time, either by +cyg_strata_init_cfi_XX or by a +platform-specific initialization routine, then it cannot be +const. + + + + Flash Structure + +Internally the flash code works in terms of +cyg_flash_dev structures, and the platform +HAL should define one of these. The structure should be placed in the +cyg_flashdev table. The following fields need to be +provided: + + + + funs + +This should point at the table of functions. + + + + start + +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 start field should correspond to +the cached address. + + + + end + +The address of the last byte in the flash. It can +either be statically initialized, or +cyg_strata_init_cfi_XX will calculate +its value at run-time. + + + + num_block_infos + +This should be the number of entries in the +block_info table. It can either be +statically initialized or it will be filled in by +cyg_strata_init_cfi_XX. + + + + block_info + +The table with the block information is held in the +cyg_strata_dev structure, so this field +should just point into that structure. + + + + priv + +This field is reserved for use by the device driver. For the Strata +driver it should point at the appropriate +cyg_strata_dev structure. + + + + +The cyg_flash_dev 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 const. + + + + Multiple Devices + +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 +cyg_flash_dev structures. The table of +function pointers can usually be shared, as can the +cyg_strata_dev structure. Another approach +is to define a single cyg_flash_dev +structure but with a larger block_info +table, covering the blocks in both banks of devices. The second +approach makes more efficient use of memory. + + +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 +cyg_flash_dev structures. + + +If more than one cyg_flash_dev structure is +instantiated then the platform HAL's CDL script should implement the +CDL interface CYGHWR_IO_FLASH_DEVICE 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. + + + + Platform-Specific Macros + +The Strata driver source code includes the header files +cyg/hal/hal_arch.h and +cyg/hal/hal_io.h, 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. + + + + Cache Management + +By default the strata driver assumes that the flash can be accessed +uncached, and it will use the HAL +CYGARC_UNCACHED_ADDRESS macro to map the cached +address in the start field of the +cyg_flash_dev structure into an uncached +address. If for any reason this HAL macro is inappropriate for the +flash then an alternative macro +HAL_STRATA_UNCACHED_ADDRESS can be defined +instead. However fixing the +CYGARC_UNCACHED_ADDRESS macro is normally the +better solution. + + +If there is no way of bypassing the cache then the platform HAL should +implement the CDL interface +CYGHWR_DEVS_FLASH_STRATA_V2_CACHED_ONLY. The flash +driver will now disable and re-enable the cache as required. For +example a program operation will involve the following: + + + STRATA_INTSCACHE_STATE; + STRATA_INTSCACHE_BEGIN(); + while ( ! finished ) { + program data + } + STRATA_INTSCACHE_END(); + + +The default implementations of these INTSCACHE macros are as follows: +STATE defines any local variables that may be +needed, e.g. to save the current interrupt state; +BEGIN disables interrupts, synchronizes the data +caches, disables it, and invalidates the current contents; +END 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. + + +Some implementations of the HAL cache macros may not provide the exact +semantics required by the flash driver. For example +HAL_DCACHE_DISABLE may have an unwanted side +effect, or it may do more work than is needed here. The driver will +check for alternative macros +HAL_STRATA_INTSCACHE_STATE, +HAL_STRATA_INTSCACHE_BEGIN and +HAL_STRATA_INTSCACHE_END, using these instead of +the defaults. + + + + + + + + Strata-Specific Functions + + + Strata + driver-specific functions + + + + +#include <cyg/io/strata_dev.h> + + + void cyg_strata_read_devid_XX + struct cyg_flash_dev* device + cyg_uint32* manufacturer + cyg_uint32* device + + + int cyg_strata_unlock_all_j3_XX + struct cyg_flash_dev* device + + + + + + Description + +The driver provides two sets of functions specific to Strata devices +and not accessible via the standard eCos flash API. Both may be used +safely before the flash subsystem is initialized using +cyg_flash_init. + + +cyg_strata_read_devid_XX can be used to get the +manufacturer and device codes. Typically it is called from a +platform-specific driver initialization routine, allowing the platform +HAL to adapt to the actual device present on the board. This may be +useful if a board may get manufactured with several different and +somewhat incompatible chips, although usually +cyg_strata_init_cfi is the better approach. It +may also be used during testing and porting to check that the chip is +working correctly. + + +cyg_strata_unlock_all_j3_XX is only useful with +28FxxxJ3 chips and compatibles. These do not allow individual blocks +to be unlocked. Hence the standard block unlock functionality is +expensive: it requires checking the locked state of every block, +unlocking every block, and then relocking all the blocks that should +still be blocked. Worse, unlocking every block is a time-consuming +operation, taking approximately a second, that needs to run with +interrupts disabled. For many applications it is better to just ignore +the chip's locking capabilities and run with all blocks permanently +unlocked. Invoking cyg_strata_unlock_all_j3_XX +during manufacture or when the board is commissioned achieves this. + + + + + Index: packages/devs/flash/intel/stratav2/current/include/strata_dev.h =================================================================== RCS file: packages/devs/flash/intel/stratav2/current/include/strata_dev.h diff -N packages/devs/flash/intel/stratav2/current/include/strata_dev.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/intel/stratav2/current/include/strata_dev.h 18 Nov 2008 01:01:18 -0000 @@ -0,0 +1,162 @@ +#ifndef CYGONCE_DEVS_FLASH_STRATA_DEV_V2_H +# define CYGONCE_DEVS_FLASH_STRATA_DEV_V2_H +//========================================================================== +// +// strata_dev.h +// +// Flash driver for the Intel Strata family - driver details +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005, 2006 eCosCentric Ltd +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// 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: 2005-06-11 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include + +externC int cyg_strata_init_nop(struct cyg_flash_dev*); +externC size_t cyg_strata_query_nop(struct cyg_flash_dev*, void*, const size_t); +externC int cyg_strata_hwr_map_error_nop(struct cyg_flash_dev*, int); +externC int cyg_strata_lock_nop(struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_nop(struct cyg_flash_dev*, const cyg_flashaddr_t); + +externC void cyg_strata_read_devid_8( struct cyg_flash_dev*, cyg_uint32*, cyg_uint32*); +externC void cyg_strata_read_devid_16( struct cyg_flash_dev*, cyg_uint32*, cyg_uint32*); +externC void cyg_strata_read_devid_32( struct cyg_flash_dev*, cyg_uint32*, cyg_uint32*); +externC void cyg_strata_read_devid_88( struct cyg_flash_dev*, cyg_uint32*, cyg_uint32*); +externC void cyg_strata_read_devid_8888( struct cyg_flash_dev*, cyg_uint32*, cyg_uint32*); +externC void cyg_strata_read_devid_1616( struct cyg_flash_dev*, cyg_uint32*, cyg_uint32*); +externC void cyg_strata_read_devid_16as8( struct cyg_flash_dev*, cyg_uint32*, cyg_uint32*); + +externC int cyg_strata_init_check_devid_8( struct cyg_flash_dev*); +externC int cyg_strata_init_check_devid_16( struct cyg_flash_dev*); +externC int cyg_strata_init_check_devid_32( struct cyg_flash_dev*); +externC int cyg_strata_init_check_devid_88( struct cyg_flash_dev*); +externC int cyg_strata_init_check_devid_8888( struct cyg_flash_dev*); +externC int cyg_strata_init_check_devid_1616( struct cyg_flash_dev*); +externC int cyg_strata_init_check_devid_16as8( struct cyg_flash_dev*); + +externC int cyg_strata_init_cfi_8( struct cyg_flash_dev*); +externC int cyg_strata_init_cfi_16( struct cyg_flash_dev*); +externC int cyg_strata_init_cfi_32( struct cyg_flash_dev*); +externC int cyg_strata_init_cfi_88( struct cyg_flash_dev*); +externC int cyg_strata_init_cfi_8888( struct cyg_flash_dev*); +externC int cyg_strata_init_cfi_1616( struct cyg_flash_dev*); +externC int cyg_strata_init_cfi_16as8( struct cyg_flash_dev*); + +externC int cyg_strata_erase_8( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_strata_erase_16( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_strata_erase_32( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_strata_erase_88( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_strata_erase_8888( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_strata_erase_1616( struct cyg_flash_dev*, cyg_flashaddr_t); +externC int cyg_strata_erase_16as8( struct cyg_flash_dev*, cyg_flashaddr_t); + +externC int cyg_strata_program_8( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_program_16( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_program_32( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_program_88( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_program_8888( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_program_1616( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_program_16as8( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); + +externC int cyg_strata_bufprogram_8( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_bufprogram_16( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_bufprogram_32( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_bufprogram_88( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_bufprogram_8888( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_bufprogram_1616( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); +externC int cyg_strata_bufprogram_16as8( struct cyg_flash_dev*, cyg_flashaddr_t, const void*, size_t); + +externC int cyg_strata_lock_j3_8( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_j3_16( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_j3_32( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_j3_88( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_j3_1616( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_j3_16as8( struct cyg_flash_dev*, const cyg_flashaddr_t); + +externC int cyg_strata_lock_k3_8( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_k3_16( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_k3_32( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_k3_88( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_k3_1616( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_lock_k3_16as8( struct cyg_flash_dev*, const cyg_flashaddr_t); + +externC int cyg_strata_unlock_j3_8( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_j3_16( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_j3_32( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_j3_88( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_j3_1616( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_j3_16as8( struct cyg_flash_dev*, const cyg_flashaddr_t); + +externC int cyg_strata_unlock_k3_8( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_k3_16( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_k3_32( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_k3_88( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_k3_1616( struct cyg_flash_dev*, const cyg_flashaddr_t); +externC int cyg_strata_unlock_k3_16as8( struct cyg_flash_dev*, const cyg_flashaddr_t); + +// An additional exported interface for application developers. +externC int cyg_strata_unlock_all_j3_8( const cyg_flashaddr_t); +externC int cyg_strata_unlock_all_j3_16( const cyg_flashaddr_t); +externC int cyg_strata_unlock_all_j3_32( const cyg_flashaddr_t); +externC int cyg_strata_unlock_all_j3_88( const cyg_flashaddr_t); +externC int cyg_strata_unlock_all_j3_1616( const cyg_flashaddr_t); +externC int cyg_strata_unlock_all_j3_16as8( const cyg_flashaddr_t); + +// The driver-specific data, pointed at by the priv field in a +// a cyg_flash_dev structure. +typedef struct cyg_strata_dev { + // The device id, mainly for use by the init_check_devid() routines + cyg_uint32 manufacturer_code; + cyg_uint32 device_code; + // The buffer size for buffered writes in words, usually 16 + cyg_uint32 bufsize; + // 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_STRATA_V2_ERASE_REGIONS]; +} cyg_strata_dev; + +#define CYG_FLASH_STRATA_MANUFACTURER_INTEL 0x0089 +#define CYG_FLASH_STRATA_MANUFACTURER_STMICRO 0x0020 + +#endif // CYGONCE_DEVS_FLASH_STRATA_DEV_V2_H Index: packages/devs/flash/intel/stratav2/current/src/strata.c =================================================================== RCS file: packages/devs/flash/intel/stratav2/current/src/strata.c diff -N packages/devs/flash/intel/stratav2/current/src/strata.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/intel/stratav2/current/src/strata.c 18 Nov 2008 01:01:18 -0000 @@ -0,0 +1,474 @@ +//========================================================================== +// +// strata.c +// +// Flash driver for the Intel Strata family +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005, 2006 eCosCentric Ltd +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// 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: 2005-06-11 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// This driver supports multiple banks of Intel Strata 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 (*hwr_map_error)(...) +// 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. +// +// The hwr_map_error is a no-op. +// +// Erase, program, and the locking functions need real +// implementations. + +// ---------------------------------------------------------------------------- +// The protocol understood by Strata flash chips and compatibles. The +// STRATA_PARALLEL() macro is used in bus configurations with multiple +// devices in parallel, to issue commands to all the devices in a +// single write. For CFI only one of the chips is queried. For READ_ID +// when getting the manufacturer and device id only a single device +// has to be queried, but when checking lock status all devices have +// to be checked. +#define STRATA_COMMAND_READ_ARRAY STRATA_SWAP(STRATA_PARALLEL(0x00FF)) +#define STRATA_COMMAND_READ_ID STRATA_SWAP(STRATA_PARALLEL(0x0090)) +#define STRATA_COMMAND_READ_STATUS STRATA_SWAP(STRATA_PARALLEL(0x0070)) +#define STRATA_COMMAND_CLEAR_STATUS STRATA_SWAP(STRATA_PARALLEL(0x0050)) +#define STRATA_COMMAND_PROGRAM_WORD STRATA_SWAP(STRATA_PARALLEL(0x0040)) +#define STRATA_COMMAND_WRITE_BUFFER STRATA_SWAP(STRATA_PARALLEL(0x00E8)) +#define STRATA_COMMAND_WRITE_CONFIRM STRATA_SWAP(STRATA_PARALLEL(0x00D0)) +#define STRATA_COMMAND_ERASE STRATA_SWAP(STRATA_PARALLEL(0x0020)) +#define STRATA_COMMAND_ERASE_CONFIRM STRATA_SWAP(STRATA_PARALLEL(0x00D0)) +#define STRATA_COMMAND_CFI STRATA_SWAP((0x0098)) +#define STRATA_COMMAND_CONFIGURATION STRATA_SWAP(STRATA_PARALLEL(0x00B8)) +#define STRATA_COMMAND_LOCK_BLOCK_0 STRATA_SWAP(STRATA_PARALLEL(0x0060)) +#define STRATA_COMMAND_LOCK_BLOCK_1 STRATA_SWAP(STRATA_PARALLEL(0x0001)) +#define STRATA_COMMAND_UNLOCK_BLOCK_0 STRATA_SWAP(STRATA_PARALLEL(0x0060)) +#define STRATA_COMMAND_UNLOCK_BLOCK_1 STRATA_SWAP(STRATA_PARALLEL(0x00D0)) +#define STRATA_COMMAND_UNLOCK_ALL_0 STRATA_SWAP(STRATA_PARALLEL(0x0060)) +#define STRATA_COMMAND_UNLOCK_ALL_1 STRATA_SWAP(STRATA_PARALLEL(0x00D0)) + +// 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 STRATA_OFFSET_CFI_Q STRATA_OFFSET_CFI_DATA(0x0010) +#define STRATA_OFFSET_CFI_SIZE STRATA_OFFSET_CFI_DATA(0x0027) +#define STRATA_OFFSET_CFI_WRITE_BUFFER_LSB STRATA_OFFSET_CFI_DATA(0x002A) +#define STRATA_OFFSET_CFI_WRITE_BUFFER_MSB STRATA_OFFSET_CFI_DATA(0x002B) +#define STRATA_OFFSET_CFI_BLOCK_REGIONS STRATA_OFFSET_CFI_DATA(0x002C) +#define STRATA_OFFSET_CFI_BLOCK_COUNT_LSB(_i_) STRATA_OFFSET_CFI_DATA(0x002D + (4 * _i_)) +#define STRATA_OFFSET_CFI_BLOCK_COUNT_MSB(_i_) STRATA_OFFSET_CFI_DATA(0x002E + (4 * _i_)) +#define STRATA_OFFSET_CFI_BLOCK_SIZE_LSB(_i_) STRATA_OFFSET_CFI_DATA(0x002F + (4 * _i_)) +#define STRATA_OFFSET_CFI_BLOCK_SIZE_MSB(_i_) STRATA_OFFSET_CFI_DATA(0x0030 + (4 * _i_)) + +#define STRATA_STATUS_SR7 STRATA_SWAP(STRATA_PARALLEL(0x0080)) +#define STRATA_STATUS_SR6 STRATA_SWAP(STRATA_PARALLEL(0x0040)) +#define STRATA_STATUS_SR5 STRATA_SWAP(STRATA_PARALLEL(0x0020)) +#define STRATA_STATUS_SR4 STRATA_SWAP(STRATA_PARALLEL(0x0010)) +#define STRATA_STATUS_SR3 STRATA_SWAP(STRATA_PARALLEL(0x0008)) +#define STRATA_STATUS_SR2 STRATA_SWAP(STRATA_PARALLEL(0x0004)) +#define STRATA_STATUS_SR1 STRATA_SWAP(STRATA_PARALLEL(0x0002)) +#define STRATA_STATUS_SR0 STRATA_SWAP(STRATA_PARALLEL(0x0001)) +#define STRATA_ID_LOCKED STRATA_SWAP(STRATA_PARALLEL(0x01)) + +// 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 STRATA_NEXT_DATUM_8(_ptr_) (*_ptr_++) +#if CYG_BYTEORDER == CYG_LSBFIRST +# define STRATA_NEXT_DATUM_16(_ptr_) \ + ({ \ + cyg_uint16 _result_; \ + _result_ = (_ptr_[1] << 8) | _ptr_[0]; \ + _ptr_ += 2; \ + _result_; }) + +# define STRATA_NEXT_DATUM_32(_ptr_) \ + ({ \ + cyg_uint32 _result_; \ + _result_ = (_ptr_[3] << 24) | (_ptr_[2] << 16) | (_ptr_[1] << 8) | _ptr_[0]; \ + _ptr_ += 4; \ + _result_; }) +#else +# define STRATA_NEXT_DATUM_16(_ptr_) \ + ({ \ + cyg_uint16 _result_; \ + _result_ = (_ptr_[0] << 8) | _ptr_[1]; \ + _ptr_ += 2; \ + _result_; }) + +# define STRATA_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_STRATA_UNCACHED_ADDRESS() can be supplied by one of the HAL +// packages. Otherwise if CYGHWR_DEVS_FLASH_STRATA_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_STRATA_UNCACHED_ADDRESS) +# define STRATA_UNCACHED_ADDRESS(_addr_) (volatile STRATA_TYPE*)HAL_STRATA_UNCACHED_ADDRESS(_addr_) +#elif !defined(CYGHWR_DEVS_FLASH_STRATA_V2_CACHED_ONLY) +# ifndef CYGARC_UNCACHED_ADDRESS +# error Cache should be bypassed but CYGARC_UNCACHED_ADDRESS is not defined. +# endif +# define STRATA_UNCACHED_ADDRESS(_addr_) (volatile STRATA_TYPE*)CYGARC_UNCACHED_ADDRESS(_addr_) +#else +# define STRATA_UNCACHED_ADDRESS(_addr_) (volatile STRATA_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 STRATA_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_STRATA_SWAP) +# define STRATA_SWAP(_data_) HAL_STRATA_SWAP(_data_) +#else +# define STRATA_SWAP(_data_) (_data_) +#endif +#if defined(HAL_STRATA_UNSWAP) +# define STRATA_UNSWAP(_data_) HAL_STRATA_UNSWAP(_data_) +#else +# define STRATA_UNSWAP(_data_) (_data_) +#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, needed if +// CYGHWR_DEVS_FLASH_STRATA_V2_CACHED_ONLY is implemented i.e. if it +// is necessary to disable the cache to get direct access to the flash. +// 2) control interrupts only, the default if the cache can be bypassed +// when accessing the flash. +// 3) do nothing, 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_STRATA_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 STRATA_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. Then 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 STRATA_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 STRATA_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_STRATA_V2_LEAVE_INTERRUPTS_ENABLED) + +# define STRATA_INTSCACHE_DEFAULT_STATE int _saved_ints_ +# define STRATA_INTSCACHE_DEFAULT_BEGIN() HAL_DISABLE_INTERRUPTS(_saved_ints_) +// 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 STRATA_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 STRATA_INTSCACHE_DEFAULT_STATE CYG_EMPTY_STATEMENT +# define STRATA_INTSCACHE_DEFAULT_BEGIN() CYG_EMPTY_STATEMENT +# define STRATA_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 + +#endif + +#ifdef HAL_STRATA_INTSCACHE_STATE +# define STRATA_INTSCACHE_STATE HAL_STRATA_INTSCACHE_STATE +#else +# define STRATA_INTSCACHE_STATE STRATA_INTSCACHE_DEFAULT_STATE +#endif +#ifdef HAL_STRATA_INTSCACHE_BEGIN +# define STRATA_INTSCACHE_BEGIN HAL_STRATA_INTSCACHE_BEGIN +#else +# define STRATA_INTSCACHE_BEGIN STRATA_INTSCACHE_DEFAULT_BEGIN +#endif +#ifdef HAL_STRATA_INTSCACHE_END +# define STRATA_INTSCACHE_END HAL_STRATA_INTSCACHE_END +#else +# define STRATA_INTSCACHE_END STRATA_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 +strata_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 STRATA_SUFFIX 8 +#define STRATA_TYPE cyg_uint8 +#define STRATA_DEVCOUNT 1 +#define STRATA_NEXT_DATUM(_ptr_) STRATA_NEXT_DATUM_8(_ptr_) + +#include "strata_aux.c" + +#undef STRATA_SUFFIX +#undef STRATA_TYPE +#undef STRATA_DEVCOUNT +#undef STRATA_NEXT_DATUM + +// A single 16-bit device. +#define STRATA_SUFFIX 16 +#define STRATA_TYPE cyg_uint16 +#define STRATA_DEVCOUNT 1 +#define STRATA_NEXT_DATUM(_ptr_) STRATA_NEXT_DATUM_16(_ptr_) + +#include "strata_aux.c" + +#undef STRATA_SUFFIX +#undef STRATA_TYPE +#undef STRATA_DEVCOUNT +#undef STRATA_NEXT_DATUM + +// A single 32-bit device. +#define STRATA_SUFFIX 32 +#define STRATA_TYPE cyg_uint32 +#define STRATA_DEVCOUNT 1 +#define STRATA_NEXT_DATUM(_ptr_) STRATA_NEXT_DATUM_32(_ptr_) + +#include "strata_aux.c" + +#undef STRATA_SUFFIX +#undef STRATA_TYPE +#undef STRATA_DEVCOUNT +#undef STRATA_NEXT_DATUM + +// Two 8-bit devices, giving a 16-bit bus. +#define STRATA_SUFFIX 88 +#define STRATA_TYPE cyg_uint16 +#define STRATA_DEVCOUNT 2 +#define STRATA_NEXT_DATUM(_ptr_) STRATA_NEXT_DATUM_16(_ptr_) +#define STRATA_PARALLEL(_cmd_) ((_cmd_ << 8) | _cmd_) + +#include "strata_aux.c" + +#undef STRATA_SUFFIX +#undef STRATA_TYPE +#undef STRATA_DEVCOUNT +#undef STRATA_NEXT_DATUM + +// Four 8-bit devices, giving a 32-bit bus. +#define STRATA_SUFFIX 8888 +#define STRATA_TYPE cyg_uint32 +#define STRATA_DEVCOUNT 4 +#define STRATA_NEXT_DATUM(_ptr_) STRATA_NEXT_DATUM_32(_ptr_) +#define STRATA_PARALLEL(_cmd_) ((_cmd_ << 24) | (_cmd_ << 16) | (_cmd_ << 8) | _cmd_) + +#include "strata_aux.c" + +#undef STRATA_SUFFIX +#undef STRATA_TYPE +#undef STRATA_DEVCOUNT +#undef STRATA_NEXT_DATUM + +// Two 16-bit devices, giving a 32-bit bus. +#define STRATA_SUFFIX 1616 +#define STRATA_TYPE cyg_uint32 +#define STRATA_DEVCOUNT 2 +#define STRATA_NEXT_DATUM(_ptr_) STRATA_NEXT_DATUM_32(_ptr_) +#define STRATA_PARALLEL(_cmd_) ((_cmd_ << 16) | _cmd_) + +#include "strata_aux.c" + +#undef STRATA_SUFFIX +#undef STRATA_TYPE +#undef STRATA_DEVCOUNT +#undef STRATA_NEXT_DATUM + +// 16AS8. A 16-bit device hooked up so that only byte accesses are +// allowed. This requires unusual offsets for the CFI and query data. +#define STRATA_SUFFIX 16as8 +#define STRATA_TYPE cyg_uint8 +#define STRATA_DEVCOUNT 1 +#define STRATA_NEXT_DATUM(_ptr_) STRATA_NEXT_DATUM_8(_ptr_) +#define STRATA_OFFSET_MANUFACTURER_ID 00 +#define STRATA_OFFSET_DEVICE_ID 02 +#define STRATA_OFFSET_LOCK_STATUS 04 +#define STRATA_OFFSET_CFI_DATA(_idx_) (2 * _idx_) + +#include "strata_aux.c" Index: packages/devs/flash/intel/stratav2/current/src/strata_aux.c =================================================================== RCS file: packages/devs/flash/intel/stratav2/current/src/strata_aux.c diff -N packages/devs/flash/intel/stratav2/current/src/strata_aux.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/intel/stratav2/current/src/strata_aux.c 18 Nov 2008 01:01:19 -0000 @@ -0,0 +1,871 @@ +//========================================================================== +// +// strata_aux.c +// +// Flash driver for the Intel Strata family - implementation. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 2005, 2006 eCosCentric Ltd +// +// 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., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. +// +// 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: 2005-06-11 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +// This file is #include'd multiple times from the main strata.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. STRATA_SUFFIX is #define'd before +// each #include of strata_aux.c + +#ifndef STRATA_STR +# define STRATA_STR1(_a_) # _a_ +# define STRATA_STR(_a_) STRATA_STR1(_a_) +# define STRATA_CONCAT3_AUX(_a_, _b_, _c_) _a_##_b_##_c_ +# define STRATA_CONCAT3(_a_, _b_, _c_) STRATA_CONCAT3_AUX(_a_, _b_, _c_) +#endif + +#define STRATA_FNNAME(_base_) STRATA_CONCAT3(_base_, _, STRATA_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 STRATA_RAMFNDECL(_base_, _args_) \ + STRATA_FNNAME(_base_) _args_ __attribute__((section (".2ram." STRATA_STR(_base_) "_" STRATA_STR(STRATA_SUFFIX)))) + +// Calculate the CFI and ID offsets based on the device count. The +// main code may override this for specific configurations, e.g. 16as8 +#ifndef STRATA_OFFSET_CFI_DATA +# define STRATA_OFFSET_CFI_DATA(_idx_) _idx_ +#endif +#ifndef STRATA_OFFSET_MANUFACTURER_ID +# define STRATA_OFFSET_MANUFACTURER_ID 0x00 +#endif +#ifndef STRATA_OFFSET_DEVICE_ID +# define STRATA_OFFSET_DEVICE_ID 0x01 +#endif +#ifndef STRATA_OFFSET_LOCK_STATUS +# define STRATA_OFFSET_LOCK_STATUS 0x02 +#endif + + +// For parallel operation commands are issued in parallel and status +// bits are checked in parallel. +#ifndef STRATA_PARALLEL +# define STRATA_PARALLEL(_cmd_) (_cmd_) +#endif + +// ---------------------------------------------------------------------------- +// Diagnostic routines. + +#if 0 +#define sf_diag( __fmt, ... ) diag_printf("SF: %s[%d]: " __fmt, __FUNCTION__, __LINE__, __VA_ARGS__ ); +#define sf_dump_buf( __addr, __size ) diag_dump_buf( __addr, __size ) +#else +#define sf_diag( __fmt, ... ) +#define sf_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 void STRATA_RAMFNDECL(strata_hw_query, (volatile STRATA_TYPE*, cyg_uint32*, cyg_uint32*)); +static int STRATA_RAMFNDECL(strata_hw_cfi, (struct cyg_flash_dev*, cyg_strata_dev*, volatile STRATA_TYPE*)); +static int STRATA_RAMFNDECL(strata_hw_erase, (volatile STRATA_TYPE*)); +static int STRATA_RAMFNDECL(strata_hw_program, (volatile STRATA_TYPE*, const cyg_uint8*, cyg_uint32 count)); +static int STRATA_RAMFNDECL(strata_hw_bufprogram, (volatile STRATA_TYPE*, const cyg_uint8*, cyg_uint32 count)); +static int STRATA_RAMFNDECL(strata_hw_is_locked, (volatile STRATA_TYPE*)); +static int STRATA_RAMFNDECL(strata_hw_lock_j3, (volatile STRATA_TYPE*)); +static int STRATA_RAMFNDECL(strata_hw_unlock_all_j3, (volatile STRATA_TYPE*)); +static int STRATA_RAMFNDECL(strata_hw_lock_k3, (volatile STRATA_TYPE*)); +static int STRATA_RAMFNDECL(strata_hw_unlock_k3, (volatile STRATA_TYPE*)); + +// 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 void +STRATA_FNNAME(strata_hw_query)(volatile STRATA_TYPE* addr, cyg_uint32* manufacturer, cyg_uint32* device) +{ + sf_diag("addr %08x cmd %08x width %d\n", addr, STRATA_COMMAND_READ_ID, sizeof(addr[0]) ); + addr[0] = STRATA_COMMAND_READ_ID; + *manufacturer = STRATA_UNSWAP(addr[STRATA_OFFSET_MANUFACTURER_ID]); + *device = STRATA_UNSWAP(addr[STRATA_OFFSET_DEVICE_ID]); + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); +} + +// 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 +STRATA_FNNAME(strata_hw_cfi)(struct cyg_flash_dev* dev, cyg_strata_dev* strata_dev, volatile STRATA_TYPE* addr) +{ + int dev_size; + int i; + int erase_regions; + cyg_uint8 writebuffer_lsb, writebuffer_msb; + cyg_uint32 writebuffer; + + sf_diag("addr %08x %d cmd %08x\n",addr, sizeof(STRATA_TYPE), STRATA_COMMAND_CFI); + // Just a single write is needed to put the device into CFI mode + addr[0] = STRATA_COMMAND_CFI; + sf_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' != (STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_Q]) & 0x00FF)) { + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + 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 << (STRATA_UNSWAP(addr[STRATA_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 2. A value of 0 indicates that + // only chip erase is supported, but the driver does not cope + // with that. + erase_regions = STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_BLOCK_REGIONS]) & 0x00FF; + if (erase_regions > CYGNUM_DEVS_FLASH_STRATA_V2_ERASE_REGIONS) { + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + 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 = STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_BLOCK_COUNT_LSB(i)]) & 0x00FF; + cyg_uint32 count_msb = STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_BLOCK_COUNT_MSB(i)]) & 0x00FF; + cyg_uint32 size_lsb = STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_BLOCK_SIZE_LSB(i)]) & 0x00FF; + cyg_uint32 size_msb = STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_BLOCK_SIZE_MSB(i)]) & 0x00FF; + + count = ((count_msb << 8) | count_lsb) + 1; + size = (size_msb << 16) | (size_lsb << 8); + sf_diag("erase_region %d count %d size %d\n", i, count, size); + strata_dev->block_info[i].block_size = (size_t) size * STRATA_DEVCOUNT; + strata_dev->block_info[i].blocks = count; + } + + writebuffer_lsb = STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_WRITE_BUFFER_LSB]) & 0x00FF; + writebuffer_msb = STRATA_UNSWAP(addr[STRATA_OFFSET_CFI_WRITE_BUFFER_MSB]) & 0x00FF; + writebuffer = 1 << writebuffer_lsb; + + strata_dev->bufsize = writebuffer / sizeof(STRATA_TYPE); + + // Get out of CFI mode + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + + 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 +STRATA_FNNAME(strata_hw_erase)(volatile STRATA_TYPE* addr) +{ + STRATA_TYPE status; + int result = CYG_FLASH_ERR_OK; + int retries; + + sf_diag("addr %08x fc %d\n",addr, first_call); + // Start the erase operation + addr[0] = STRATA_COMMAND_CLEAR_STATUS; + addr[0] = STRATA_COMMAND_ERASE; + addr[0] = STRATA_COMMAND_ERASE_CONFIRM; + + // All chips are now erasing in parallel. Loop until all have + // completed. The SR7 bit will be clear while the erase is + // proceeding, set when is has completed. For an already erased + // block in a parallel configuration we'll read the 0xff erased + // value so the test succeeds there as well. + for (retries = CYGNUM_DEVS_FLASH_STRATA_V2_ERASE_TIMEOUT; + retries > 0; + retries--) { + status = addr[0]; + if ((status & STRATA_STATUS_SR7) == STRATA_STATUS_SR7) { + break; + } + } + + if (retries == 0) { + // The world is messed up. One or more chips are still + // erasing, status bits may be set, etc. This should not + // happen, the erase timeout should be big enough. There + // is no easy way to get back into a sane state. + return CYG_FLASH_ERR_DRV_TIMEOUT; + } + + // The erase operation has completed. First get the chip(s) back + // into a sane state. + addr[0] = STRATA_COMMAND_READ_STATUS; + status = addr[0]; + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + + // According to the data sheet the bits should be checked in order SR5, + // SR3, SR2. This does not appear to work, at least on a J3. If the + // block is locked then SR5 is set as well as SR1, so the wrong error + // code would be returned. + if (status & STRATA_STATUS_SR1) { + result = CYG_FLASH_ERR_PROTECT; + } else if (status & STRATA_STATUS_SR3) { + result = CYG_FLASH_ERR_LOW_VOLTAGE; + } else if (status & STRATA_STATUS_SR5) { + if (status & STRATA_STATUS_SR4) { + result = CYG_FLASH_ERR_PROTOCOL; + } else { + result = CYG_FLASH_ERR_ERASE; + } + } + sf_diag("status %08x result %d\n", status, result); + return result; +} + +// Write data to flash, using individual word writes. The destination +// address will be aligned in a way suitable for the bus. The source +// address need not be aligned. The count is in STRATA_TYPE's, i.e. as +// per the bus alignment, not in bytes. +static int +STRATA_FNNAME(strata_hw_program)(volatile STRATA_TYPE* addr, const cyg_uint8* buf, cyg_uint32 count) +{ + int i; + int result = CYG_FLASH_ERR_OK; + int retries = CYGNUM_DEVS_FLASH_STRATA_V2_PROGRAM_TIMEOUT; + STRATA_TYPE status; + +// sf_diag("addr %08x %d\n",addr, count); + addr[0] = STRATA_COMMAND_CLEAR_STATUS; + for (i = 0; (i < count) && (result == CYG_FLASH_ERR_OK); i++) { + addr[i] = STRATA_COMMAND_PROGRAM_WORD; + addr[i] = STRATA_NEXT_DATUM(buf); + + // The data is now being written. While the write is in progress + // SR7 will be clear. + do { + status = addr[i]; + } while ((--retries > 0) && ((status & STRATA_STATUS_SR7) != STRATA_STATUS_SR7)); + + // The status bits may not all change at the same time. + // Re-read just to be sure + status = addr[i]; + + // Again the order here is not that in the datasheet. If the block is + // locked then SR4 will be set as well as SR2. + if (retries == 0) { + result = CYG_FLASH_ERR_DRV_TIMEOUT; + } else if (status & STRATA_STATUS_SR1) { + result = CYG_FLASH_ERR_PROTECT; + } else if (status & STRATA_STATUS_SR3) { + result = CYG_FLASH_ERR_LOW_VOLTAGE; + } else if (status & STRATA_STATUS_SR4) { + result = CYG_FLASH_ERR_PROGRAM; + } + } + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + return result; +} + +static int +STRATA_FNNAME(strata_hw_bufprogram)(volatile STRATA_TYPE* addr, const cyg_uint8* buf, cyg_uint32 count) +{ + int result = CYG_FLASH_ERR_OK; + STRATA_TYPE status; + int retries = CYGNUM_DEVS_FLASH_STRATA_V2_PROGRAM_TIMEOUT; + int i; + +// sf_diag("addr %p buf %p count %d\n",addr, buf, count); + addr[0] = STRATA_COMMAND_CLEAR_STATUS; + do { + // Issue the command and check that the buffer is ready + *addr = STRATA_COMMAND_WRITE_BUFFER; + status = *addr; + } while ((--retries > 0) && ((status & STRATA_STATUS_SR7) != STRATA_STATUS_SR7)); + + // Now issue the count, data, and confirm the operation + addr[0] = STRATA_SWAP(STRATA_PARALLEL((count - 1))); + for( i = 0 ; i < count ; i++ ) + { + STRATA_TYPE val = STRATA_NEXT_DATUM(buf); + addr[i] = val; + } + addr[0] = STRATA_COMMAND_WRITE_CONFIRM; + + // The write is proceeding. Loop for status. + do { + status = addr[0]; + } while ((--retries > 0) && ((status & STRATA_STATUS_SR7) != STRATA_STATUS_SR7)); + + // Re-read status, in case bit 7 changed before the others + status = addr[0]; + +// sf_diag("status %08x retries %d SR7 %08x\n", status, retries, STRATA_STATUS_SR7); + // Again the order here is not that in the datasheet. If the block is + // locked then SR4 will be set as well as SR1. + if (retries == 0) { + result = CYG_FLASH_ERR_DRV_TIMEOUT; + } else if (status & STRATA_STATUS_SR1) { + result = CYG_FLASH_ERR_PROTECT; + } else if (status & STRATA_STATUS_SR3) { + result = CYG_FLASH_ERR_LOW_VOLTAGE; + } else if (status & STRATA_STATUS_SR4) { + result = CYG_FLASH_ERR_PROGRAM; + } + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + if( result != CYG_FLASH_ERR_OK ) + { + sf_diag("status %08x result %d\n", status, result ); + } + return result; +} + +static int +STRATA_FNNAME(strata_hw_is_locked)(volatile STRATA_TYPE* addr) +{ + int result; + addr[0] = STRATA_COMMAND_READ_ID; + sf_dump_buf(addr, 16 ); + result = addr[STRATA_OFFSET_LOCK_STATUS]; + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + sf_diag("addr %08x result %08x id_locked %08x\n",addr, result, STRATA_ID_LOCKED); + // The bottom bit always holds the block locked status. Other bits + // may get used, e.g. on the k3 family bit 1 holds the locked-down + // status. This is ignored for now. + return (0 != (result & STRATA_ID_LOCKED)); +} + +// With the J3 family locking involves checking the status register. +// There is no individual block unlock, instead code has to unlock +// all blocks and then selectively relock them. +static int +STRATA_FNNAME(strata_hw_lock_j3)(volatile STRATA_TYPE* addr) +{ + int result = CYG_FLASH_ERR_OK; + STRATA_TYPE status; + + sf_diag("addr %08x\n",addr); + addr[0] = STRATA_COMMAND_CLEAR_STATUS; + addr[0] = STRATA_COMMAND_LOCK_BLOCK_0; + addr[0] = STRATA_COMMAND_LOCK_BLOCK_1; + do { + status = addr[0]; + } while ((status & STRATA_STATUS_SR7) != STRATA_STATUS_SR7); + status = addr[0]; + if (status & STRATA_STATUS_SR3) { + result = CYG_FLASH_ERR_LOW_VOLTAGE; + } else if ((status & STRATA_STATUS_SR5) && (status & STRATA_STATUS_SR4)) { + result = CYG_FLASH_ERR_PROTOCOL; + } else if (status & STRATA_STATUS_SR4) { + result = CYG_FLASH_ERR_LOCK; + } + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + sf_diag("addr %08x status %08x result %d\n",addr, status, result ); + return result; +} + +static int +STRATA_FNNAME(strata_hw_unlock_all_j3)(volatile STRATA_TYPE* addr) +{ + int result = CYG_FLASH_ERR_OK; + STRATA_TYPE status; + + sf_diag("addr %08x\n",addr); + addr[0] = STRATA_COMMAND_CLEAR_STATUS; + addr[0] = STRATA_COMMAND_UNLOCK_ALL_0; + addr[0] = STRATA_COMMAND_UNLOCK_ALL_1; + do { + status = addr[0]; + } while ((status & STRATA_STATUS_SR7) != STRATA_STATUS_SR7); + status = addr[0]; + if (status & STRATA_STATUS_SR3) { + result = CYG_FLASH_ERR_LOW_VOLTAGE; + } else if ((status & STRATA_STATUS_SR5) && (status & STRATA_STATUS_SR4)) { + result = CYG_FLASH_ERR_PROTOCOL; + } else if (status & STRATA_STATUS_SR4) { + result = CYG_FLASH_ERR_LOCK; + } + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + sf_diag("addr %08x status %08x result %d\n",addr, status, result ); + return result; +} + +// With the K3 family locking involves checking the id rather than the +// status register, and there is a block unlock command. There is no +// exported support for manipulating the block low-down bits so it is +// assumed these bits remain clear. +static int +STRATA_FNNAME(strata_hw_lock_k3)(volatile STRATA_TYPE* addr) +{ + int result = CYG_FLASH_ERR_OK; + STRATA_TYPE status; + + sf_diag("addr %08x\n",addr); + do { + addr[0] = STRATA_COMMAND_LOCK_BLOCK_0; + addr[0] = STRATA_COMMAND_LOCK_BLOCK_1; + addr[0] = STRATA_COMMAND_READ_ID; + status = addr[STRATA_OFFSET_LOCK_STATUS]; + } while ((status & STRATA_ID_LOCKED) != STRATA_ID_LOCKED); + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + return result; +} + +static int +STRATA_FNNAME(strata_hw_unlock_k3)(volatile STRATA_TYPE* addr) +{ + int result = CYG_FLASH_ERR_OK; + STRATA_TYPE status; + + do { + addr[0] = STRATA_COMMAND_UNLOCK_BLOCK_0; + addr[0] = STRATA_COMMAND_UNLOCK_BLOCK_1; + addr[0] = STRATA_COMMAND_READ_ID; + status = addr[STRATA_OFFSET_LOCK_STATUS]; + } while ((status & STRATA_ID_LOCKED) != 0); + addr[0] = STRATA_COMMAND_READ_ARRAY; + HAL_MEMORY_BARRIER(); + 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. +void +STRATA_FNNAME(cyg_strata_read_devid) (struct cyg_flash_dev* dev, cyg_uint32* manufacturer, cyg_uint32* device) +{ + int (*query_fn)(volatile STRATA_TYPE*, cyg_uint32*, cyg_uint32*); + volatile STRATA_TYPE* uncached; + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + + uncached = STRATA_UNCACHED_ADDRESS(dev->start); + query_fn = (int (*)(volatile STRATA_TYPE*, cyg_uint32*, cyg_uint32*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_query) ); + STRATA_INTSCACHE_BEGIN(); + (*query_fn)(uncached, manufacturer, device); + STRATA_INTSCACHE_END(); +} + +// Validate that the device statically configured is the one on the +// board. +int +STRATA_FNNAME(cyg_strata_init_check_devid)(struct cyg_flash_dev* dev) +{ + cyg_strata_dev* strata_dev; + cyg_uint32 manufacturer, device; + + sf_diag("\n", 0); + strata_dev = (cyg_strata_dev*) dev->priv; + STRATA_FNNAME(cyg_strata_read_devid)(dev, &manufacturer, &device); + if ((manufacturer != strata_dev->manufacturer_code) || + (device != strata_dev->device_code)) { + return CYG_FLASH_ERR_DRV_WRONG_PART; + } + // 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 +STRATA_FNNAME(cyg_strata_init_cfi)(struct cyg_flash_dev* dev) +{ + int (*cfi_fn)(struct cyg_flash_dev*, cyg_strata_dev*, volatile STRATA_TYPE*); + volatile STRATA_TYPE* uncached; + cyg_strata_dev* strata_dev; + int result; + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + strata_dev = (cyg_strata_dev*) dev->priv; // Remove const, only place where this is needed. + uncached = STRATA_UNCACHED_ADDRESS(dev->start); + cfi_fn = (int (*)(struct cyg_flash_dev*, cyg_strata_dev*, volatile STRATA_TYPE*)) + cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_cfi)); + + STRATA_INTSCACHE_BEGIN(); + result = (*cfi_fn)(dev, strata_dev, uncached); + STRATA_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++) { + size += (dev->block_info[i].block_size * dev->block_info[i].blocks); + } + dev->end = dev->start + size - 1; + } + return result; +} + +// Erase a single block. The calling code will have supplied a pointer +// aligned to a block boundary. +int +STRATA_FNNAME(cyg_strata_erase)(struct cyg_flash_dev* dev, cyg_flashaddr_t dest) +{ + int (*erase_fn)(volatile STRATA_TYPE*); + volatile STRATA_TYPE* uncached; + cyg_flashaddr_t block_start; + size_t block_size; + int result; + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + CYG_ASSERT((dest >= dev->start) && (dest <= dev->end), "flash address out of device range"); + + strata_get_block_info(dev, dest, &block_start, &block_size); + CYG_ASSERT(dest == block_start, "erase address should be the start of a flash block"); + + uncached = STRATA_UNCACHED_ADDRESS(dest); + erase_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_erase) ); + + STRATA_INTSCACHE_BEGIN(); + result = (*erase_fn)(uncached); + STRATA_INTSCACHE_END(); + return result; +} + +// Write some data to the flash. The destination must be aligned +// appropriately for the bus width (not the device width). Higher +// level code guarantees that the data will not straddle a block +// boundary. +int +STRATA_FNNAME(cyg_strata_program)(struct cyg_flash_dev* dev, cyg_flashaddr_t dest, const void* src, size_t len) +{ + int (*program_fn)(volatile STRATA_TYPE*, const cyg_uint8*, cyg_uint32); + volatile STRATA_TYPE* uncached; + const cyg_uint8* data; + int result = CYG_FLASH_ERR_OK; + STRATA_INTSCACHE_STATE; + + sf_diag("dest %p src %p len %p(%d) end %p\n", dest, src, len, len, dest+len-1 ); + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + CYG_ASSERT((dest >= dev->start) && ((CYG_ADDRESS)dest <= dev->end), "flash address out of device range"); + + // 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(STRATA_TYPE) - 1))) || + (0 != (len & (sizeof(STRATA_TYPE) - 1)))) { + return CYG_FLASH_ERR_INVALID; + } + + uncached = STRATA_UNCACHED_ADDRESS(dest); + data = (const cyg_uint8*) src; + program_fn = (int (*)(volatile STRATA_TYPE*, const cyg_uint8*, cyg_uint32)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_program) ); + + STRATA_INTSCACHE_BEGIN(); + result = (*program_fn)(uncached, data, len / sizeof(STRATA_TYPE)); + STRATA_INTSCACHE_END(); + return result; +} + +// Write some data to the flash. The destination must be aligned +// appropriately for the bus width (not the device width). +int +STRATA_FNNAME(cyg_strata_bufprogram)(struct cyg_flash_dev* dev, cyg_flashaddr_t dest, const void* src, size_t len) +{ + int (*program_fn)(volatile STRATA_TYPE*, const cyg_uint8*, cyg_uint32); + volatile STRATA_TYPE* uncached; + const cyg_uint8* data; + int bufsize; + size_t to_write, first_write, this_write; + int result = CYG_FLASH_ERR_OK; + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + CYG_CHECK_DATA_PTR(dev, "valid flash device pointer required"); + CYG_ASSERT((dest >= dev->start) && ((CYG_ADDRESS)dest <= dev->end), "flash address out of device range"); + + bufsize = ((const cyg_strata_dev*)dev->priv)->bufsize; + + // 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(STRATA_TYPE) - 1))) || + (0 != (len & (sizeof(STRATA_TYPE) - 1)))) { + return CYG_FLASH_ERR_INVALID; + } + + uncached = STRATA_UNCACHED_ADDRESS(dest); + + data = (const cyg_uint8*) src; + program_fn = (int (*)(volatile STRATA_TYPE*, const cyg_uint8*, cyg_uint32)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_bufprogram) ); + + // Buffering works best when the data is aligned to a suitable + // boundary, so the first write size may be smaller than the + // buffer size to achieve alignment. + if ((CYG_ADDRWORD)uncached & ((bufsize * sizeof(STRATA_TYPE)) - 1)) { + first_write = (CYG_ADDRWORD)uncached & ((bufsize * sizeof(STRATA_TYPE)) - 1); + first_write /= sizeof(STRATA_TYPE); + first_write = bufsize - first_write; + } else { + first_write = 0; + } + + STRATA_INTSCACHE_BEGIN(); + for (to_write = len/sizeof(STRATA_TYPE); to_write > 0; ) { + + if (first_write) { + this_write = first_write; + first_write = 0; + } else { + this_write = bufsize; + } + if (this_write > to_write) { + this_write = to_write; + } + result = (*program_fn)(uncached, data, this_write); + if (result != CYG_FLASH_ERR_OK) { + break; + } + to_write -= this_write; + if (to_write > 0) { + uncached += this_write; + data += sizeof(STRATA_TYPE) * this_write; + } + } + STRATA_INTSCACHE_END(); + return result; +} + +int +STRATA_FNNAME(cyg_strata_lock_j3)(struct cyg_flash_dev* dev, const cyg_flashaddr_t dest) +{ + volatile STRATA_TYPE* uncached; + int result; + int (*lock_fn)(volatile STRATA_TYPE*); + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + 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 = STRATA_UNCACHED_ADDRESS(dest); + lock_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_lock_j3) ); + STRATA_INTSCACHE_BEGIN(); + result = (*lock_fn)(uncached); + STRATA_INTSCACHE_END(); + return result; +} + +int +STRATA_FNNAME(cyg_strata_unlock_j3)(struct cyg_flash_dev* dev, const cyg_flashaddr_t dest) +{ + int (*locked_fn)(volatile STRATA_TYPE*); + int (*lock_fn)(volatile STRATA_TYPE*); + int (*unlock_all_fn)(volatile STRATA_TYPE*); + cyg_uint8 locked_bits[(CYGNUM_DEVS_FLASH_STRATA_V2_BLOCKS + 7) / 8]; + int i, j; + int current_block; + volatile STRATA_TYPE* uncached; + volatile STRATA_TYPE* uncached_block; + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + locked_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_is_locked)); + lock_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_lock_j3)); + unlock_all_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_unlock_all_j3)); + + memset(locked_bits, 0, sizeof(locked_bits)); + + uncached = STRATA_UNCACHED_ADDRESS(dev->start); + uncached_block = STRATA_UNCACHED_ADDRESS(dest); + + STRATA_INTSCACHE_BEGIN(); + + // The obvious optimization: no point in doing anything if the + // block is already unlocked. + if (! (*locked_fn)(uncached_block)) { + STRATA_INTSCACHE_END(); + return CYG_FLASH_ERR_OK; + } + + for (i = 0, current_block = 0; i < dev->num_block_infos; i++) { + sf_diag("block_info[%d] n %d sz %d\n",i, dev->block_info[i].blocks, dev->block_info[i].block_size ); + for (j = 0; j < dev->block_info[i].blocks; j++, current_block++) { + CYG_LOOP_INVARIANT(current_block < CYGNUM_DEVS_FLASH_STRATA_V2_BLOCKS, "Device has too many blocks"); + if ((uncached != uncached_block) && (*locked_fn)(uncached)) { + locked_bits[current_block >> 3] |= (0x01 << (current_block & 0x07)); + } + uncached += dev->block_info[i].block_size/sizeof(STRATA_TYPE); + } + } + sf_diag("locked bits:\n", 0 ); + sf_dump_buf( locked_bits, sizeof(locked_bits) ); + uncached = STRATA_UNCACHED_ADDRESS(dev->start); + (*unlock_all_fn)(uncached); + for (i = 0, current_block = 0; i < dev->num_block_infos; i++) { + for (j = 0; j < dev->block_info[i].blocks; j++, current_block++) { + if (locked_bits[current_block >> 3] & (0x01 << (current_block & 0x07))) { + (*lock_fn)(uncached); + } + uncached += dev->block_info[i].block_size/sizeof(STRATA_TYPE); + } + } + STRATA_INTSCACHE_END(); + return CYG_FLASH_ERR_OK; +} + +// An additional exported interface to make life easier for +// application developers. This code assumes the pointer is for a +// strata flash device. +int +STRATA_FNNAME(cyg_strata_unlock_all_j3)(const cyg_flashaddr_t dest) +{ + cyg_flash_info_t info; + volatile STRATA_TYPE* uncached; + int (*unlock_all_fn)(volatile STRATA_TYPE*); + int result; + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + result = cyg_flash_get_info_addr(dest, &info); + if (CYG_FLASH_ERR_OK != result) { + return result; + } + + uncached = STRATA_UNCACHED_ADDRESS(info.start); + unlock_all_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_unlock_all_j3)); + STRATA_INTSCACHE_BEGIN(); + result = (*unlock_all_fn)(uncached); + STRATA_INTSCACHE_END(); + return result; +} + +int +STRATA_FNNAME(cyg_strata_lock_k3)(struct cyg_flash_dev* dev, const cyg_flashaddr_t dest) +{ + volatile STRATA_TYPE* uncached; + int result; + int (*lock_fn)(volatile STRATA_TYPE*); + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + 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 = STRATA_UNCACHED_ADDRESS(dest); + lock_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_lock_k3) ); + STRATA_INTSCACHE_BEGIN(); + result = (*lock_fn)(uncached); + STRATA_INTSCACHE_END(); + return result; +} + +int +STRATA_FNNAME(cyg_strata_unlock_k3)(struct cyg_flash_dev* dev, const cyg_flashaddr_t dest) +{ + volatile STRATA_TYPE* uncached; + int result; + int (*unlock_fn)(volatile STRATA_TYPE*); + STRATA_INTSCACHE_STATE; + + sf_diag("\n", 0); + 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 = STRATA_UNCACHED_ADDRESS(dest); + unlock_fn = (int (*)(volatile STRATA_TYPE*)) cyg_flash_anonymizer( & STRATA_FNNAME(strata_hw_unlock_k3) ); + STRATA_INTSCACHE_BEGIN(); + result = (*unlock_fn)(uncached); + STRATA_INTSCACHE_END(); + return result; +} + +// ---------------------------------------------------------------------------- +// Clean up the various #define's so this file can be #include'd again +#undef STRATA_FNNAME +#undef STRATA_RAMFNDECL +#undef STRATA_OFFSET_MANUFACTURER_ID +#undef STRATA_OFFSET_DEVICE_ID +#undef STRATA_OFFSET_LOCK_STATUS +#undef STRATA_OFFSET_CFI_DATA +#undef STRATA_PARALLEL