Attached... -- eCosCentric Limited http://www.eCosCentric.com/ The eCos experts Barnwell House, Barnwell Drive, Cambridge, UK. Tel: +44 1223 245571 Registered in England and Wales: Reg No 4422071. ------["Si fractum non sit, noli id reficere"]------ Opinions==mine
Index: packages/devs/flash/atmel/dataflash/current/ChangeLog =================================================================== RCS file: packages/devs/flash/atmel/dataflash/current/ChangeLog diff -N packages/devs/flash/atmel/dataflash/current/ChangeLog --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/atmel/dataflash/current/ChangeLog 18 Nov 2008 01:05:46 -0000 @@ -0,0 +1,96 @@ +2005-06-29 Jani Monoses <[EMAIL PROTECTED]> + + * include/dataflash.h: Allow the package to be compiled without + io/flash. Return correct value from cyg_dataflash_get_page_count() + +2004-12-02 Bart Veer <[EMAIL PROTECTED]> + + * include/dataflash.h, + src/devs_flash_atmel_dataflash_flash_dev_funs.c: include + <cyg/io/flash_dev.h> explicitly rather than using _FLASH_PRIVATE_ + +2004-11-29 Bart Veer <[EMAIL PROTECTED]> + + (df_flash_hwr_map_error): this is now internal to the driver, no + longer needed by the generic flash code. + * src/devs_flash_atmel_dataflash_flash_dev_funs.c: use the dummy + query/lock/unlock functions provided by the generic flash code + +2004-11-22 Bart Veer <[EMAIL PROTECTED]> + + * include/dataflash.h, src/devs_flash_atmel_dataflash.c, + src/devs_flash_atmel_dataflash_flash_dev_funs.c: merge the config + and priv structures, removing the duplicate spi_dev data in the + process. Adjust device driver API as per changes to the generic + flash code. + * src/devs_flash_atmel_dataflash_flash_dev_funs.c (df_flash_init): + Rename cyg_block_info to cyg_flash_block_info + +2004-11-21 Bart Veer <[EMAIL PROTECTED]> + + * cdl/devs_flash_atmel_dataflash.cdl: CYGHWR_IO_FLASH_DEVICE_V2 is + now implicit + +2004-11-20 Bart Veer <[EMAIL PROTECTED]> + + * cdl/devs_flash_atmel_dataflash.cdl: data flash requires indirect + read support in the main flash code. + +2004-10-07 Savin Zlobec <[EMAIL PROTECTED]> + + * include/dataflash.h: + * src/devs_flash_atmel_dataflash.c: + Changed the API to be more consistent, included error + reporting and added blocking/non blocking mode of operation. + * src/devs_flash_atmel_dataflash_flash_dev_funs.c: + Synced with new API and set the block size to DataFlash's + native page size. + +2004-10-07 Andrew Lunn <[EMAIL PROTECTED]> + + * cdl/devs_flash_atmel_dataflash.cdl: Remove + CYGSEM_IO_FLASH_READ_INDIRECT which only legacy drivers should use + when they provide a flash_read_buf function. For V2 drivers + providing a read function in the device structure is sufficient. + +2004-09-07 Savin Zlobec <[EMAIL PROTECTED]> + + * cdl/devs_flash_atmel_dataflash.cdl: + * include/dataflash.h: + * src/devs_flash_atmel_dataflash.c: + * src/devs_flash_atmel_dataflash_flash_dev_funs.c: + Atmel DataFlash driver implementation. + + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 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#### +//=========================================================================== Index: packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl =================================================================== RCS file: packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl diff -N packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl 18 Nov 2008 01:05:46 -0000 @@ -0,0 +1,71 @@ +# ==================================================================== +# +# devs_flash_atmel_dataflash.cdl +# +# Atmel DataFlash parts support +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 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): Savin Zlobec <[EMAIL PROTECTED]> +# Date: 2004-08-27 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_FLASH_ATMEL_DATAFLASH { + display "Atmel DataFlash parts support" + description "Support for Atmel DataFlash" + active_if CYGPKG_IO_SPI + requires CYGPKG_ERROR + hardware + compile devs_flash_atmel_dataflash.c + include_dir cyg/io + + cdl_interface CYGPKG_DEVS_FLASH_ATMEL_DATAFLASH_FLASH_DEV { + display "Support for DataFlash IO Flash interface" + flavor bool + active_if CYGPKG_IO_FLASH + implements CYGHWR_IO_FLASH_DEVICE + implements CYGHWR_IO_FLASH_INDIRECT_READS + compile devs_flash_atmel_dataflash_flash_dev_funs.c + description "This option will be enabled by platforms which + need to support access to DataFlash through IO Flash API." + } +} + +# EOF devs_flash_atmel_dataflash.cdl Index: packages/devs/flash/atmel/dataflash/current/include/dataflash.h =================================================================== RCS file: packages/devs/flash/atmel/dataflash/current/include/dataflash.h diff -N packages/devs/flash/atmel/dataflash/current/include/dataflash.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/atmel/dataflash/current/include/dataflash.h 18 Nov 2008 01:05:46 -0000 @@ -0,0 +1,249 @@ +#ifndef CYGONCE_DATAFLASH_H +#define CYGONCE_DATAFLASH_H +//========================================================================== +// +// dataflash.h +// +// DataFlash series flash driver defines +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 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): Savin Zlobec <[EMAIL PROTECTED]> +// Date: 2004-08-27 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/devs_flash_atmel_dataflash.h> + +#include <cyg/infra/cyg_type.h> +#include <cyg/hal/drv_api.h> +#include <cyg/io/spi.h> + +//---------------------------------------------------------------------------- + +enum { + CYG_DATAFLASH_ERR_OK = 0, // No error + CYG_DATAFLASH_ERR_INVALID = 1, // Invalid address error + CYG_DATAFLASH_ERR_WRONG_PART = 2, // Unsupported device error + CYG_DATAFLASH_ERR_TIMEOUT = 3, // Operation timeout error + CYG_DATAFLASH_ERR_COMPARE = 4 // Buffer - main memory compare error +}; + +enum { + CYG_DATAFLASH_STATE_IDLE = 0, + CYG_DATAFLASH_STATE_BUSY = 1 +}; + +//---------------------------------------------------------------------------- + +typedef struct cyg_dataflash_dev_info_s +{ + cyg_uint8 device_id; // Device ID + cyg_uint16 page_size; // Page size in bytes + cyg_uint16 page_count; // Total number of pages + cyg_uint8 baddr_bits; // Bits used for byte address in addressing seq + cyg_uint16 block_size; // Block size in pages + cyg_uint16 sector_sizes[64]; // Sector sizes in blocks + cyg_uint16 sector_count; // Total number of sectors +} cyg_dataflash_dev_info_t; + +typedef struct cyg_dataflash_device_s +{ + const cyg_dataflash_dev_info_t *info; // DataFlash device info + cyg_spi_device *spi_dev; // SPI device + cyg_drv_mutex_t lock; // Access lock + cyg_bool polled; // Polled mode flag + cyg_bool blocking; // Blocking mode flag + int state; // Current state (IDLE, BUSY, ...) + cyg_uint8 busy_buf; // Current busy buffer number +} cyg_dataflash_device_t; + +//---------------------------------------------------------------------------- +#ifdef CYGPKG_IO_FLASH +#include <cyg/io/flash.h> +#include <cyg/io/flash_dev.h> + +typedef struct cyg_dataflash_flash_dev_priv_s +{ + cyg_int16 start_sector; // Start sector of flash driver space + cyg_int16 end_sector; // End sector of flash driver space + cyg_dataflash_device_t dev; // DataFlash device + cyg_uint32 start_page; // Start page of flash driver space + cyg_uint32 end_page; // End page of flash driver space + cyg_flash_block_info_t block_info[1]; +} cyg_dataflash_flash_dev_priv_t; + +externC struct cyg_flash_dev_funs cyg_dataflash_flash_dev_funs; + +#define CYG_DATAFLASH_FLASH_DRIVER(name, _sdev, _addr, _start, _end) \ + static cyg_dataflash_flash_dev_priv_t cyg_dataflash_priv_ ## name = { \ + .start_sector = _start, \ + .end_sector = _end, \ + .dev.spi_dev = _sdev, \ + }; \ + CYG_FLASH_DRIVER(name, \ + &cyg_dataflash_flash_dev_funs, \ + 0, \ + _addr, \ + 0, \ + 1, \ + cyg_dataflash_priv_ ## name.block_info, \ + & cyg_dataflash_priv_ ## name \ + ) + +#endif +//---------------------------------------------------------------------------- + +static inline cyg_uint8 +cyg_dataflash_get_device_id(cyg_dataflash_device_t *dev) +{ + return dev->info->device_id; +} + +static inline cyg_uint16 +cyg_dataflash_get_page_size(cyg_dataflash_device_t *dev) +{ + return dev->info->page_size; +} + +static inline cyg_uint16 +cyg_dataflash_get_page_count(cyg_dataflash_device_t *dev) +{ + return dev->info->page_count; +} + +static inline cyg_uint16 +cyg_dataflash_get_block_size(cyg_dataflash_device_t *dev) +{ + return dev->info->block_size; +} + +static inline cyg_uint16 +cyg_dataflash_get_sector_size(cyg_dataflash_device_t *dev, cyg_uint8 sector_num) +{ + return dev->info->sector_sizes[sector_num]; +} + +static inline cyg_uint16 +cyg_dataflash_get_sector_count(cyg_dataflash_device_t *dev) +{ + return dev->info->sector_count; +} + +static inline void +cyg_dataflash_set_polled_operation(cyg_dataflash_device_t *dev, cyg_bool polled) +{ + dev->polled = polled; +} + +static inline void +cyg_dataflash_set_blocking_operation(cyg_dataflash_device_t *dev, cyg_bool block) +{ + dev->blocking = block; +} + +//---------------------------------------------------------------------------- + +externC int cyg_dataflash_init(cyg_bool polled, + cyg_dataflash_device_t *dev); + +externC int cyg_dataflash_aquire(cyg_dataflash_device_t *dev); + +externC int cyg_dataflash_release(cyg_dataflash_device_t *dev); + +externC cyg_uint16 cyg_dataflash_get_sector_start(cyg_dataflash_device_t *dev, + cyg_uint16 sector_num); + +externC int cyg_dataflash_wait_ready(cyg_dataflash_device_t *dev); + +externC int cyg_dataflash_read_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos); + +externC int cyg_dataflash_write_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + const cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos); + +externC int cyg_dataflash_mem_to_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num); + +externC int cyg_dataflash_program_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool erase); + +externC int cyg_dataflash_compare_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num); + +externC int cyg_dataflash_erase(cyg_dataflash_device_t *dev, + cyg_uint32 page_num); + +externC int cyg_dataflash_erase_block(cyg_dataflash_device_t *dev, + cyg_uint32 block_num); + +externC int cyg_dataflash_auto_rewrite(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num); + +externC int cyg_dataflash_read(cyg_dataflash_device_t *dev, + cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos); + +externC int cyg_dataflash_program(cyg_dataflash_device_t *dev, + const cyg_uint8 *buf, + cyg_uint32 *len, + cyg_uint32 pos, + cyg_bool erase, + cyg_bool verify); + +//---------------------------------------------------------------------------- + +#endif // CYGONCE_DATAFLASH_H + +//---------------------------------------------------------------------------- +// End of dataflash.h Index: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c =================================================================== RCS file: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c diff -N packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c 18 Nov 2008 01:05:46 -0000 @@ -0,0 +1,923 @@ +//========================================================================== +// +// devs_flash_atmel_dataflash.c +// +// Atmel DataFlash series flash driver +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 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): Savin Zlobec <[EMAIL PROTECTED]> +// Date: 2004-08-27 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/hal.h> +#include <pkgconf/devs_flash_atmel_dataflash.h> + +#include <cyg/infra/diag.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/hal/drv_api.h> +#include <cyg/io/spi.h> +#include <cyg/io/dataflash.h> + +// -------------------------------------------------------------------------- +// DataFlash command opcodes + +// Read commands opcodes +#define DF_CONT_ARRAY_READ_CMD 0x68 +#define DF_MMEM_PAGE_READ_CMD 0x52 +#define DF_BUF1_READ_CMD 0x54 +#define DF_BUF2_READ_CMD 0x56 +#define DF_STATUS_READ_CMD 0x57 + +// Program and erase commands opcodes +#define DF_BUF1_WRITE_CMD 0x84 +#define DF_BUF2_WRITE_CMD 0x87 +#define DF_BUF1_PROG_W_ERASE_CMD 0x83 +#define DF_BUF2_PROG_W_ERASE_CMD 0x86 +#define DF_BUF1_PROG_WO_ERASE_CMD 0x88 +#define DF_BUF2_PROG_WO_ERASE_CMD 0x89 +#define DF_PAGE_ERASE_CMD 0x81 +#define DF_BLOCK_ERASE_CMD 0x50 +#define DF_PROG_THROUGH_BUF1_CMD 0x82 +#define DF_PROG_THROUGH_BUF2_CMD 0x85 + +// Additional commands opcodes +#define DF_TRANSFER_TO_BUF1_CMD 0x53 +#define DF_TRANSFER_TO_BUF2_CMD 0x55 +#define DF_BUF1_COMPARE_CMD 0x60 +#define DF_BUF2_COMPARE_CMD 0x61 +#define DF_AUTO_REWRITE_THROUGH_BUF1_CMD 0x58 +#define DF_AUTO_REWRITE_THROUGH_BUF2_CMD 0x59 + +//---------------------------------------------------------------------------- + +#define DATA_BUF_NONE 0x00 // Data buffer number for no buffer +#define DATA_BUF_ALL 0xFF // Data buffer number for all buffers + +//---------------------------------------------------------------------------- + +typedef struct df_status_s +{ + cyg_uint8 reserved:2; + cyg_uint8 device_id:4; + cyg_uint8 compare_err:1; + cyg_uint8 ready:1; +} df_status_t; + +//---------------------------------------------------------------------------- + +static const cyg_dataflash_dev_info_t df_dev_info[] = +{ + { // AT45DB011B + device_id: 0x03, + page_size: 264, + page_count: 512, + baddr_bits: 9, + block_size: 8, + sector_sizes: { 1, 31, 32 }, + sector_count: 3 + }, + { // AT45DB021B + device_id: 0x05, + page_size: 264, + page_count: 1024, + baddr_bits: 9, + block_size: 8, + sector_sizes: { 1, 31, 32, 64 }, + sector_count: 4 + }, + { // AT45DB041B + device_id: 0x07, + page_size: 264, + page_count: 2048, + baddr_bits: 9, + block_size: 8, + sector_sizes: { 1, 31, 32, 64, 64, 64 }, + sector_count: 6 + }, + { // AT45DB081B + device_id: 0x09, + page_size: 264, + page_count: 4096, + baddr_bits: 9, + block_size: 8, + sector_sizes: { 1, 31, 32, 64, 64, 64, 64, 64, 64, 64 }, + sector_count: 10 + }, + { // AT45DB161B + device_id: 0x0B, + page_size: 528, + page_count: 4096, + baddr_bits: 10, + block_size: 8, + sector_sizes: { 1, 31, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32 }, + sector_count: 17 + }, + { // AT45DB321B + device_id: 0x0D, + page_size: 528, + page_count: 8192, + baddr_bits: 10, + block_size: 8, + sector_sizes: { 1, 63, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64 }, + sector_count: 17 + }, + { // AT45DB642 + device_id: 0x0F, + page_size: 1056, + page_count: 8192, + baddr_bits: 11, + block_size: 8, + sector_sizes: { 1, 31, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32 }, + sector_count: 35 + }, + { 0 } +}; + +//---------------------------------------------------------------------------- + +static void +df_compose_addr(cyg_dataflash_device_t *dev, + cyg_uint8 *cmd_buf, + cyg_uint16 page_addr, + cyg_uint16 byte_addr) +{ + cyg_uint32 baddr_bits = dev->info->baddr_bits; + cyg_uint32 addr; + + addr = (page_addr << baddr_bits) | (byte_addr & ((1<<baddr_bits) - 1)); + + cmd_buf[1] = (addr >> 16) & 0xFF; + cmd_buf[2] = (addr >> 8) & 0xFF; + cmd_buf[3] = addr & 0xFF; +} + +static df_status_t +df_read_status(cyg_dataflash_device_t *dev) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + const cyg_uint8 cmd_buf[2] = { DF_STATUS_READ_CMD, 0 }; + cyg_uint8 rx_buf[2]; + df_status_t *status; + + cyg_spi_transaction_transfer(spi_dev, true, 2, cmd_buf, rx_buf, true); + + status = (df_status_t *) &rx_buf[1]; + + return *status; +} + +static void +df_set_busy_buf(cyg_dataflash_device_t *dev, cyg_uint8 buf_num) +{ + dev->state = CYG_DATAFLASH_STATE_BUSY; + dev->busy_buf = buf_num; +} + +static void +df_set_busy(cyg_dataflash_device_t *dev) +{ + df_set_busy_buf(dev, DATA_BUF_ALL); +} + +static int +df_wait_ready_buf(cyg_dataflash_device_t *dev, cyg_uint8 buf_num) +{ + df_status_t status; + + if (CYG_DATAFLASH_STATE_IDLE == dev->state) + return CYG_DATAFLASH_ERR_OK; + + if (DATA_BUF_ALL == buf_num || + DATA_BUF_ALL == dev->busy_buf || + dev->busy_buf == buf_num) + { + // REMIND: this loop should have an timeout + // in case of device malfunction + + do + { + status = df_read_status(dev); + } while (0 == status.ready); + + dev->state = CYG_DATAFLASH_STATE_IDLE; + dev->busy_buf = DATA_BUF_NONE; + } + + return CYG_DATAFLASH_ERR_OK; + +} + +static int +df_wait_ready(cyg_dataflash_device_t *dev) +{ + return df_wait_ready_buf(dev, DATA_BUF_ALL); +} + +static void +df_detect_device(cyg_dataflash_device_t *dev) +{ + const cyg_dataflash_dev_info_t *dev_info; + cyg_spi_device *spi_dev = dev->spi_dev; + df_status_t status; + + cyg_spi_transaction_begin(spi_dev); + status = df_read_status(dev); + cyg_spi_transaction_end(spi_dev); + + dev_info = df_dev_info; + + while (dev_info->device_id != 0) + { + if (status.device_id == dev_info->device_id) + { + dev->info = dev_info; + return; + } + dev_info++; + } + dev->info = NULL; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_init() + +int +cyg_dataflash_init(cyg_bool polled, + cyg_dataflash_device_t *dev) +{ + dev->polled = polled; + dev->blocking = false; + dev->state = CYG_DATAFLASH_STATE_IDLE; + dev->busy_buf = DATA_BUF_NONE; + + cyg_drv_mutex_init(&dev->lock); + + df_detect_device(dev); + + if (NULL == dev->info) + return CYG_DATAFLASH_ERR_WRONG_PART; + else + return CYG_DATAFLASH_ERR_OK; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_aquire() + +int +cyg_dataflash_aquire(cyg_dataflash_device_t *dev) +{ + while (!cyg_drv_mutex_lock(&dev->lock)); + return CYG_DATAFLASH_ERR_OK; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_release() + +int +cyg_dataflash_release(cyg_dataflash_device_t *dev) +{ + int err; + + err = df_wait_ready(dev); + + cyg_drv_mutex_unlock(&dev->lock); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_get_sector_start() + +cyg_uint16 +cyg_dataflash_get_sector_start(cyg_dataflash_device_t *dev, + cyg_uint16 sector_num) +{ + cyg_uint16 res, i; + + if (sector_num >= dev->info->sector_count) + return 0; + + res = 0; + for (i = 0; i < sector_num; i++) + res += dev->info->sector_sizes[i]; + + return res; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_wait_ready() + +int +cyg_dataflash_wait_ready(cyg_dataflash_device_t *dev) +{ + return df_wait_ready(dev); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_read_buf() + +int +cyg_dataflash_read_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos) + +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[5]; + + // Check if the position is inside the page + if (pos >= dev->info->page_size) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + if (1 == buf_num) cmd_buf[0] = DF_BUF1_READ_CMD; + else if (2 == buf_num) cmd_buf[0] = DF_BUF2_READ_CMD; + else + return CYG_DATAFLASH_ERR_INVALID; + + df_compose_addr(dev, cmd_buf, 0, pos); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the target buffer to become ready + err = df_wait_ready_buf(dev, buf_num); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send command and read data + + cyg_spi_transaction_transfer(spi_dev, true, 5, cmd_buf, NULL, false); + cyg_spi_transaction_transfer(spi_dev, dev->polled, len, buf, buf, true); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_write_buf() + +int +cyg_dataflash_write_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + const cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + + // Check if the position is inside the page + if (pos >= dev->info->page_size) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + if (1 == buf_num) cmd_buf[0] = DF_BUF1_WRITE_CMD; + else if (2 == buf_num) cmd_buf[0] = DF_BUF2_WRITE_CMD; + else + return CYG_DATAFLASH_ERR_INVALID; + + df_compose_addr(dev, cmd_buf, 0, pos); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the target buffer to become ready + err = df_wait_ready_buf(dev, buf_num); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send command and data + + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, false); + cyg_spi_transaction_transfer(spi_dev, dev->polled, + len, buf, NULL, true); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_mem_to_buf() + +int +cyg_dataflash_mem_to_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + + // Check if the page number is inside the flash + if (page_num >= dev->info->page_count) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + if (1 == buf_num) cmd_buf[0] = DF_TRANSFER_TO_BUF1_CMD; + else if (2 == buf_num) cmd_buf[0] = DF_TRANSFER_TO_BUF2_CMD; + else + return CYG_DATAFLASH_ERR_INVALID; + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the device to become ready + err = df_wait_ready(dev); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send the command + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + // Mark the target buffer as busy + df_set_busy_buf(dev, buf_num); + + // Wait if in blocking mode + if (dev->blocking) + err = df_wait_ready(dev); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_program_buf() + +int +cyg_dataflash_program_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool erase) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + + // Check if the page number is inside the flash + if (page_num >= dev->info->page_count) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + if (erase) + { + if (1 == buf_num) cmd_buf[0] = DF_BUF1_PROG_W_ERASE_CMD; + else if (2 == buf_num) cmd_buf[0] = DF_BUF2_PROG_W_ERASE_CMD; + else + return CYG_DATAFLASH_ERR_INVALID; + } + else + { + if (1 == buf_num) cmd_buf[0] = DF_BUF1_PROG_WO_ERASE_CMD; + else if (2 == buf_num) cmd_buf[0] = DF_BUF2_PROG_WO_ERASE_CMD; + else + return CYG_DATAFLASH_ERR_INVALID; + } + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the device to become ready + err = df_wait_ready(dev); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send the command + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + // Mark the target buffer as busy + df_set_busy_buf(dev, buf_num); + + // Wait if in blocking mode + if (dev->blocking) + err = df_wait_ready(dev); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_compare_buf() + +int +cyg_dataflash_compare_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + df_status_t status; + + // Check if the page number is inside the flash + if (page_num >= dev->info->page_count) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + if (1 == buf_num) cmd_buf[0] = DF_BUF1_COMPARE_CMD; + else if (2 == buf_num) cmd_buf[0] = DF_BUF2_COMPARE_CMD; + else + return CYG_DATAFLASH_ERR_INVALID; + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the device to become ready + err = df_wait_ready(dev); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send the command + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + // Wait for the device to become ready + df_set_busy(dev); + err = df_wait_ready(dev); + + // Read the result of memory compare + + if (CYG_DATAFLASH_ERR_OK == err) + { + status = df_read_status(dev); + if (status.compare_err) + err = CYG_DATAFLASH_ERR_COMPARE; + } + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_erase() + +int +cyg_dataflash_erase(cyg_dataflash_device_t *dev, + cyg_uint32 page_num) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + + // Check if the page number is inside the flash + if (page_num >= dev->info->page_count) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + cmd_buf[0] = DF_PAGE_ERASE_CMD; + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the device to become ready + err = df_wait_ready(dev); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send the command + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + // Set device state to busy + df_set_busy_buf(dev, DATA_BUF_NONE); + + // Wait if in blocking mode + if (dev->blocking) + err = df_wait_ready(dev); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_erase_block() + +int +cyg_dataflash_erase_block(cyg_dataflash_device_t *dev, + cyg_uint32 block_num) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + + // Check if the block number is inside the flash + if (block_num >= (dev->info->page_count >> 3)) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + cmd_buf[0] = DF_BLOCK_ERASE_CMD; + df_compose_addr(dev, cmd_buf, block_num << 3, 0); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the device to become ready + err = df_wait_ready(dev); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send the command + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + // Set device state to busy + df_set_busy_buf(dev, DATA_BUF_NONE); + + // Wait if in blocking mode + if (dev->blocking) + err = df_wait_ready(dev); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_auto_rewrite() + +int +cyg_dataflash_auto_rewrite(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + + // Check if the page number is inside the flash + if (page_num >= dev->info->page_count) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + if (1 == buf_num) cmd_buf[0] = DF_AUTO_REWRITE_THROUGH_BUF1_CMD; + else if (2 == buf_num) cmd_buf[0] = DF_AUTO_REWRITE_THROUGH_BUF2_CMD; + else + return CYG_DATAFLASH_ERR_INVALID; + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the device to become ready + err = df_wait_ready(dev); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send the command + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + // Mark the target buffer as busy + df_set_busy_buf(dev, buf_num); + + // Wait if in blocking mode + if (dev->blocking) + err = df_wait_ready(dev); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_read() + +int +cyg_dataflash_read(cyg_dataflash_device_t *dev, + cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[8]; + cyg_uint32 page_num, page_pos; + + // Calculate page number and position from given absolute position + + page_num = pos / dev->info->page_size; + page_pos = pos % dev->info->page_size; + + // Check if the page number is inside the flash + if (page_num >= dev->info->page_count) + return CYG_DATAFLASH_ERR_INVALID; + + // Compose DataFlash command + + cmd_buf[0] = DF_CONT_ARRAY_READ_CMD; + df_compose_addr(dev, cmd_buf, page_num, page_pos); + + cyg_spi_transaction_begin(spi_dev); + + // Wait for the device to become ready + err = df_wait_ready(dev); + + if (CYG_DATAFLASH_ERR_OK == err) + { + // Send the command and read data from DataFlash main memory + + cyg_spi_transaction_transfer(spi_dev, true, 8, cmd_buf, NULL, false); + cyg_spi_transaction_transfer(spi_dev, dev->polled, len, buf, buf, true); + } + + cyg_spi_transaction_end(spi_dev); + + return err; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_program() + +int +cyg_dataflash_program(cyg_dataflash_device_t *dev, + const cyg_uint8 *buf, + cyg_uint32 *len, + cyg_uint32 pos, + cyg_bool erase, + cyg_bool verify) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + int err = CYG_DATAFLASH_ERR_OK; + cyg_uint8 cmd_buf[4]; + cyg_uint32 count, page_num, page_pos; + + // Calculate page number and position from given absolute position + + page_num = pos / dev->info->page_size; + page_pos = pos % dev->info->page_size; + count = *len; + + cyg_spi_transaction_begin(spi_dev); + + // Wait for device to become ready + err = df_wait_ready(dev); + if (CYG_DATAFLASH_ERR_OK != err) + goto out; + + // Loop until count bytes written + + while (count > 0) + { + df_status_t status; + cyg_uint32 size; + + // Check if the current page number is inside the flash + if (page_num >= dev->info->page_count) + { + err = CYG_DATAFLASH_ERR_INVALID; + goto out; + } + + // Calculate the number of bytes to write to the current page + if ((page_pos + count) > dev->info->page_size) + size = dev->info->page_size - page_pos; + else + size = count; + + // Compose DataFlash command address + df_compose_addr(dev, cmd_buf, page_num, page_pos); + + // If we are not rewritting the whole page, then first + // read the old data from main memory to the target buffer + + if (page_pos > 0 || size < dev->info->page_size) + { + cmd_buf[0] = DF_TRANSFER_TO_BUF1_CMD; + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + df_set_busy(dev); + err = df_wait_ready(dev); + if (CYG_DATAFLASH_ERR_OK != err) + goto out; + } + + // Write data to the target buffer + + cmd_buf[0] = DF_BUF1_WRITE_CMD; + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, false); + cyg_spi_transaction_transfer(spi_dev, dev->polled, + size, buf, NULL, true); + df_set_busy(dev); + err = df_wait_ready(dev); + if (CYG_DATAFLASH_ERR_OK != err) + goto out; + + // Program data from the target buffer to main memory + // and perform an erase before if requested + + if (erase) + cmd_buf[0] = DF_BUF1_PROG_W_ERASE_CMD; + else + cmd_buf[0] = DF_BUF1_PROG_WO_ERASE_CMD; + + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + df_set_busy(dev); + err = df_wait_ready(dev); + if (CYG_DATAFLASH_ERR_OK != err) + goto out; + + // Compare the target buffer contents with the freshly + // written main memory page (if requested) + + if (verify) + { + cmd_buf[0] = DF_BUF1_COMPARE_CMD; + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + df_set_busy(dev); + err = df_wait_ready(dev); + if (CYG_DATAFLASH_ERR_OK != err) + goto out; + + status = df_read_status(dev); + + if (status.compare_err) + { + err = CYG_DATAFLASH_ERR_COMPARE; + goto out; + } + } + + // Adjust running values + + page_pos = 0; + page_num += 1; + count -= size; + buf += size; + } + +out: + cyg_spi_transaction_end(spi_dev); + + *len -= count; + + return err; +} + +//---------------------------------------------------------------------------- +// End of devs_flash_atmel_dataflash.c Index: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c =================================================================== RCS file: packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c diff -N packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c 18 Nov 2008 01:05:46 -0000 @@ -0,0 +1,224 @@ +//========================================================================== +// +// devs_flash_atmel_dataflash_flash_dev_funs.c +// +// DataFlash flash device funs +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 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): Savin Zlobec <[EMAIL PROTECTED]> +// Date: 2004-09-06 +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include <pkgconf/system.h> +#include <pkgconf/hal.h> +#include <pkgconf/devs_flash_atmel_dataflash.h> +#include <pkgconf/io_flash.h> + +#include <cyg/infra/diag.h> +#include <cyg/infra/cyg_type.h> +#include <cyg/infra/cyg_ass.h> +#include <cyg/io/spi.h> +#include <cyg/io/dataflash.h> + +// -------------------------------------------------------------------------- + +#define RETURN_ON_ERROR(_op_) \ + if (CYG_DATAFLASH_ERR_OK != (err = _op_)) return df_flash_hwr_map_error(dev, err) + +#define GOTO_ON_ERROR(_op_) \ + if (CYG_DATAFLASH_ERR_OK != (err = _op_)) goto on_error + +static int +df_flash_hwr_map_error(struct cyg_flash_dev *dev, int err) +{ + switch (err) + { + case CYG_DATAFLASH_ERR_OK: return CYG_FLASH_ERR_OK; + case CYG_DATAFLASH_ERR_INVALID: return CYG_FLASH_ERR_INVALID; + case CYG_DATAFLASH_ERR_WRONG_PART: return CYG_FLASH_ERR_DRV_WRONG_PART; + case CYG_DATAFLASH_ERR_TIMEOUT: return CYG_FLASH_ERR_DRV_TIMEOUT; + case CYG_DATAFLASH_ERR_COMPARE: return CYG_FLASH_ERR_DRV_VERIFY; + default: return CYG_FLASH_ERR_INVALID; + } +} + +// -------------------------------------------------------------------------- + +static int +df_flash_init(struct cyg_flash_dev *dev) +{ + cyg_dataflash_flash_dev_priv_t *priv; + cyg_dataflash_device_t *df_dev; + int sector_cnt; + + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + df_dev = &priv->dev; + +#ifdef CYGPKG_REDBOOT + if (cyg_dataflash_init(true, df_dev)) +#else + if (cyg_dataflash_init(false, df_dev)) +#endif + return CYG_DATAFLASH_ERR_WRONG_PART; + + cyg_dataflash_set_blocking_operation(df_dev, true); + + sector_cnt = cyg_dataflash_get_sector_count(df_dev); + + if (priv->end_sector < 0) + priv->end_sector = sector_cnt - 1; + + if (priv->start_sector >= sector_cnt || + priv->end_sector >= sector_cnt || + priv->end_sector < priv->start_sector) + return CYG_DATAFLASH_ERR_INVALID; + + priv->start_page = cyg_dataflash_get_block_size(df_dev) * + cyg_dataflash_get_sector_start(df_dev, priv->start_sector); + + priv->end_page = cyg_dataflash_get_block_size(df_dev) * + (cyg_dataflash_get_sector_start(df_dev, priv->end_sector) + + cyg_dataflash_get_sector_size(df_dev, priv->end_sector)); + + dev->end = (cyg_flashaddr_t)(dev->start + + ((priv->end_page - priv->start_page) * + cyg_dataflash_get_page_size(df_dev)) - 1); + priv->block_info[0].block_size = cyg_dataflash_get_page_size(df_dev); + priv->block_info[0].blocks = priv->end_page - priv->start_page; + + return CYG_DATAFLASH_ERR_OK; +} + +static int +df_flash_erase_block(struct cyg_flash_dev *dev, + cyg_flashaddr_t base) +{ + cyg_dataflash_flash_dev_priv_t *priv; + cyg_uint32 page; + int err; + + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + + page = priv->start_page + ((base - dev->start) / + cyg_dataflash_get_page_size(&priv->dev)); + + RETURN_ON_ERROR( cyg_dataflash_aquire(&priv->dev) ); + GOTO_ON_ERROR( cyg_dataflash_erase(&priv->dev, page) ); + RETURN_ON_ERROR( cyg_dataflash_release(&priv->dev) ); + + return CYG_DATAFLASH_ERR_OK; + +on_error: + cyg_dataflash_release(&priv->dev); + return df_flash_hwr_map_error(dev, err); +} + +static int +df_flash_program(struct cyg_flash_dev *dev, + cyg_flashaddr_t base, + const void *data, + size_t len) +{ + cyg_dataflash_flash_dev_priv_t *priv; + cyg_uint32 page, pos; + int err; + + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + + page = priv->start_page + ((base - dev->start) / + cyg_dataflash_get_page_size(&priv->dev)); + pos = (base - dev->start) % cyg_dataflash_get_page_size(&priv->dev); + + RETURN_ON_ERROR( cyg_dataflash_aquire(&priv->dev) ); + GOTO_ON_ERROR( cyg_dataflash_mem_to_buf(&priv->dev, 1, page) ); + GOTO_ON_ERROR( cyg_dataflash_write_buf(&priv->dev, 1, data, len, pos) ); + GOTO_ON_ERROR( cyg_dataflash_program_buf(&priv->dev, 1, page, true) ); + RETURN_ON_ERROR( cyg_dataflash_release(&priv->dev) ); + + return CYG_DATAFLASH_ERR_OK; + +on_error: + cyg_dataflash_release(&priv->dev); + return df_flash_hwr_map_error(dev, err); +} + +static int +df_flash_read(struct cyg_flash_dev *dev, + const cyg_flashaddr_t base, + void *data, + size_t len) +{ + cyg_dataflash_flash_dev_priv_t *priv; + cyg_uint32 page, pos; + int err; + + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + + page = priv->start_page + ((base - dev->start) / + cyg_dataflash_get_page_size(&priv->dev)); + pos = (base - dev->start) % cyg_dataflash_get_page_size(&priv->dev); + + RETURN_ON_ERROR( cyg_dataflash_aquire(&priv->dev) ); + GOTO_ON_ERROR( cyg_dataflash_mem_to_buf(&priv->dev, 1, page) ); + GOTO_ON_ERROR( cyg_dataflash_read_buf(&priv->dev, 1, data, len, pos) ); + RETURN_ON_ERROR( cyg_dataflash_release(&priv->dev) ); + + return CYG_DATAFLASH_ERR_OK; + +on_error: + cyg_dataflash_release(&priv->dev); + return df_flash_hwr_map_error(dev, err); +} + +// -------------------------------------------------------------------------- + +CYG_FLASH_FUNS(cyg_dataflash_flash_dev_funs, + df_flash_init, + cyg_flash_devfn_query_nop, + df_flash_erase_block, + df_flash_program, + df_flash_read, + cyg_flash_devfn_lock_nop, + cyg_flash_devfn_unlock_nop +); + +//---------------------------------------------------------------------------- +// End of devs_flash_atmel_dataflash_flash_dev_funs.c
