Mercurial > flash_v2
changeset 1732:1646bf44203c
* 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.
| author | asl |
|---|---|
| date | Tue, 05 Oct 2004 09:19:15 +0000 |
| parents | a24c2d6d8afa |
| children | 1a23a3a30984 |
| files | packages/devs/flash/atmel/dataflash/current/ChangeLog packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl packages/devs/flash/atmel/dataflash/current/include/dataflash.h packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c |
| diffstat | 5 files changed, 1292 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/atmel/dataflash/current/ChangeLog @@ -0,0 +1,41 @@ +2004-09-07 Savin Zlobec <savin@elatec.si> + + * 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#### +//===========================================================================
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/atmel/dataflash/current/cdl/devs_flash_atmel_dataflash.cdl @@ -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 <savin@elatec.si> +# 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 + 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_DEVICE_V2 + requires CYGSEM_IO_FLASH_READ_INDIRECT + 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
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/atmel/dataflash/current/include/dataflash.h @@ -0,0 +1,229 @@ +#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 <savin@elatec.si> +// 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> + +//---------------------------------------------------------------------------- + +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_bool polled; // Polled mode flag + cyg_drv_mutex_t lock; // Access lock +} cyg_dataflash_device_t; + +//---------------------------------------------------------------------------- + +#ifdef _FLASH_PRIVATE_ +#include <cyg/io/flash.h> + +typedef struct cyg_dataflash_flash_dev_config_s +{ + cyg_spi_device **spi_dev; // SPI device + cyg_uint32 address; // Memory address (flash driver) + cyg_int16 start_sector; // Start sector of flash driver space + cyg_int16 end_sector; // End sector of flash driver space +} cyg_dataflash_flash_dev_config_t; + +typedef struct cyg_dataflash_flash_dev_priv_s +{ + 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_uint32 page_2size_log; // Page (2^n) size log +} 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_config_t config_ ## name = { \ + .spi_dev = &_sdev, \ + .address = _addr, \ + .start_sector = _start, \ + .end_sector = _end \ + }; \ + CYG_FLASH_DRIVER(name, &cyg_dataflash_flash_dev_funs, \ + &config_ ## name, 0, \ + sizeof(cyg_dataflash_flash_dev_priv_t)) + +#endif // _FLASH_PRIVATE_ + +//---------------------------------------------------------------------------- + +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_size; +} + +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; +} + +externC cyg_bool cyg_dataflash_init(cyg_spi_device *spi_dev, + cyg_bool polled, + cyg_dataflash_device_t *dev); + +externC void cyg_dataflash_aquire(cyg_dataflash_device_t *dev); + +externC void 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 void cyg_dataflash_read_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos); + +externC void cyg_dataflash_write_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + const cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos); + +externC void cyg_dataflash_mem_to_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool wait); + +externC void cyg_dataflash_program_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool erase, + cyg_bool wait); + +externC cyg_bool cyg_dataflash_compare_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num); + +externC void cyg_dataflash_erase(cyg_dataflash_device_t *dev, + cyg_uint32 page_num, + cyg_bool wait); + +externC void cyg_dataflash_erase_block(cyg_dataflash_device_t *dev, + cyg_uint32 block_num, + cyg_bool wait); + +externC void cyg_dataflash_auto_rewrite(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool wait); + +externC void cyg_dataflash_read(cyg_dataflash_device_t *dev, + cyg_uint8 *buf, + cyg_uint32 len, + cyg_uint32 pos); + +externC cyg_bool 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
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash.c @@ -0,0 +1,684 @@ +//========================================================================== +// +// 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 <savin@elatec.si> +// 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 + +//---------------------------------------------------------------------------- + +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_wait_ready(cyg_dataflash_device_t *dev) +{ + df_status_t status; + + do + { + status = df_read_status(dev); + } while (0 == status.ready); +} + +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) + { +// diag_printf("Detected DataFlash id = %d page_size=%d page_count=%d\n", +// status.device_id, dev_info->page_size, dev_info->page_count); + + dev->info = dev_info; + return; + } + dev_info++; + } + dev->info = NULL; +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_init() + +cyg_bool +cyg_dataflash_init(cyg_spi_device *spi_dev, + cyg_bool polled, + cyg_dataflash_device_t *dev) +{ + dev->spi_dev = spi_dev; + dev->polled = polled; + + cyg_drv_mutex_init(&dev->lock); + + df_detect_device(dev); + + if (NULL == dev->info) + return false; + else + return true; +} + +//---------------------------------------------------------------------------- +// 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_aquire() + +void +cyg_dataflash_aquire(cyg_dataflash_device_t *dev) +{ + while (!cyg_drv_mutex_lock(&dev->lock)); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_release() + +void +cyg_dataflash_release(cyg_dataflash_device_t *dev) +{ + cyg_drv_mutex_unlock(&dev->lock); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_read_buf() + +void +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; + cyg_uint8 cmd_buf[5]; + + pos %= dev->info->page_size; + + 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; + + df_compose_addr(dev, cmd_buf, 0, pos); + + cyg_spi_transaction_begin(spi_dev); + 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); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_write_buf() + +void +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; + cyg_uint8 cmd_buf[4]; + + pos %= dev->info->page_size; + + 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; + + df_compose_addr(dev, cmd_buf, 0, pos); + + cyg_spi_transaction_begin(spi_dev); + 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); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_mem_to_buf() + +void +cyg_dataflash_mem_to_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool wait) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + cyg_uint8 cmd_buf[4]; + + if (page_num >= dev->info->page_count) + return; + + 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; + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + df_wait_ready(dev); + + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + if (wait) + df_wait_ready(dev); + + cyg_spi_transaction_end(spi_dev); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_program_buf() + +void +cyg_dataflash_program_buf(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool erase, + cyg_bool wait) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + cyg_uint8 cmd_buf[4]; + + if (page_num >= dev->info->page_count) + return; + + 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; + } + 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; + } + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + df_wait_ready(dev); + + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + if (wait) + df_wait_ready(dev); + + cyg_spi_transaction_end(spi_dev); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_compare_buf() + +cyg_bool +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; + cyg_uint8 cmd_buf[4]; + df_status_t status; + + if (page_num >= dev->info->page_count) + return false; + + 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 false; + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + df_wait_ready(dev); + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + df_wait_ready(dev); + + status = df_read_status(dev); + + cyg_spi_transaction_end(spi_dev); + + return (!status.compare_err); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_erase() + +void +cyg_dataflash_erase(cyg_dataflash_device_t *dev, + cyg_uint32 page_num, + cyg_bool wait) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + cyg_uint8 cmd_buf[4]; + + if (page_num >= dev->info->page_count) + return; + + cmd_buf[0] = DF_PAGE_ERASE_CMD; + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + df_wait_ready(dev); + + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + if (wait) + df_wait_ready(dev); + + cyg_spi_transaction_end(spi_dev); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_erase_block() + +void +cyg_dataflash_erase_block(cyg_dataflash_device_t *dev, + cyg_uint32 block_num, + cyg_bool wait) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + cyg_uint8 cmd_buf[4]; + + if (block_num >= (dev->info->page_count >> 3)) + return; + + cmd_buf[0] = DF_BLOCK_ERASE_CMD; + df_compose_addr(dev, cmd_buf, block_num << 3, 0); + + cyg_spi_transaction_begin(spi_dev); + + df_wait_ready(dev); + + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + if (wait) + df_wait_ready(dev); + + cyg_spi_transaction_end(spi_dev); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_auto_rewrite() + +void +cyg_dataflash_auto_rewrite(cyg_dataflash_device_t *dev, + cyg_uint8 buf_num, + cyg_uint32 page_num, + cyg_bool wait) +{ + cyg_spi_device *spi_dev = dev->spi_dev; + cyg_uint8 cmd_buf[4]; + + if (page_num >= dev->info->page_count) + return; + + 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; + + df_compose_addr(dev, cmd_buf, page_num, 0); + + cyg_spi_transaction_begin(spi_dev); + + df_wait_ready(dev); + + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + + if (wait) + df_wait_ready(dev); + + cyg_spi_transaction_end(spi_dev); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_read() + +void +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; + cyg_uint8 cmd_buf[8]; + cyg_uint32 page_num, page_pos; + + page_num = pos / dev->info->page_size; + page_pos = pos % dev->info->page_size; + + cmd_buf[0] = DF_CONT_ARRAY_READ_CMD; + df_compose_addr(dev, cmd_buf, page_num, page_pos); + + cyg_spi_transaction_begin(spi_dev); + df_wait_ready(dev); + 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); +} + +//---------------------------------------------------------------------------- +// cyg_dataflash_program() + +cyg_bool +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; + cyg_uint8 cmd_buf[4]; + cyg_uint32 count, page_num, page_pos; + cyg_bool res = true; + + page_num = pos / dev->info->page_size; + page_pos = pos % dev->info->page_size; + count = *len; + +// diag_printf("\nWrite start at page=%d pos=%d size=%d\n", page_num, page_pos, *len); + + cyg_spi_transaction_begin(spi_dev); + + df_wait_ready(dev); + + while (count > 0) + { + df_status_t status; + cyg_uint32 size; + + if ((page_pos + count) > dev->info->page_size) + size = dev->info->page_size - page_pos; + else + size = count; + +// diag_printf("Writing page=%d size=%d [%02X]\n", page_num, size, *buf); + + df_compose_addr(dev, cmd_buf, page_num, page_pos); + + 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_wait_ready(dev); + } + + 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_wait_ready(dev); + + 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_wait_ready(dev); + + if (verify) + { + cmd_buf[0] = DF_BUF1_COMPARE_CMD; + cyg_spi_transaction_transfer(spi_dev, true, 4, cmd_buf, NULL, true); + df_wait_ready(dev); + + status = df_read_status(dev); + + if (status.compare_err) + { + res = false; + break; + } + } + + page_pos = 0; + page_num += 1; + count -= size; + buf += size; + } + + cyg_spi_transaction_end(spi_dev); + + *len -= count; + + return res; +} + +//---------------------------------------------------------------------------- +// End of devs_flash_atmel_dataflash.c
new file mode 100644 --- /dev/null +++ b/packages/devs/flash/atmel/dataflash/current/src/devs_flash_atmel_dataflash_flash_dev_funs.c @@ -0,0 +1,267 @@ +//========================================================================== +// +// 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 <savin@elatec.si> +// 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> + +#define _FLASH_PRIVATE_ +#include <cyg/io/dataflash.h> + +// -------------------------------------------------------------------------- + +static cyg_uint32 +get_page_2size_log(cyg_uint32 size) +{ + cyg_uint32 i; + + i = 0; + while (size != 0) + { + size >>= 1; + i++; + } + return (i-1); +} + +// -------------------------------------------------------------------------- + +static int +df_flash_init(struct cyg_flash_dev *dev) +{ + static cyg_block_info_t block_info[1]; + + cyg_dataflash_flash_dev_config_t *config; + cyg_dataflash_flash_dev_priv_t *priv; + cyg_dataflash_device_t *df_dev; + int sector_cnt; + + config = (cyg_dataflash_flash_dev_config_t *) dev->config; + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + df_dev = &priv->dev; + +// diag_printf("\nDF INIT\n"); + +#ifdef CYGPKG_REDBOOT + if (!cyg_dataflash_init(*(config->spi_dev), true, df_dev)) +#else + if (!cyg_dataflash_init(*(config->spi_dev), false, df_dev)) +#endif + return CYG_FLASH_ERR_DRV_WRONG_PART; + + sector_cnt = cyg_dataflash_get_sector_count(df_dev); + +// diag_printf("\nDF INIT sector cnt = %d\n", sector_cnt); + + if (config->end_sector < 0) + config->end_sector = sector_cnt - 1; + +// diag_printf("\nDF INIT end sector = %d\n", config->end_sector); + + if (config->start_sector >= sector_cnt || + config->end_sector >= sector_cnt || + config->end_sector < config->start_sector) + return CYG_FLASH_ERR_INVALID; + + priv->start_page = cyg_dataflash_get_block_size(df_dev) * + cyg_dataflash_get_sector_start(df_dev, config->start_sector); + + priv->end_page = cyg_dataflash_get_block_size(df_dev) * + (cyg_dataflash_get_sector_start(df_dev, config->end_sector) + + cyg_dataflash_get_sector_size(df_dev, config->end_sector)); + +// diag_printf("\nDF INIT start page = %d end page = %d\n", +// priv->start_page, priv->end_page); + + priv->page_2size_log = + get_page_2size_log(cyg_dataflash_get_page_size(df_dev)); + +// diag_printf("\nDF INIT page_2size_log = %d\n", priv->page_2size_log); + + dev->start = (cyg_flashaddr_t)config->address; + dev->end = (cyg_flashaddr_t)(config->address + + ((priv->end_page - priv->start_page) << priv->page_2size_log)); + +// diag_printf("\nDF INIT start = %x end = %x\n", +// dev->start, dev->end); + + dev->num_block_infos = 1; + dev->block_info = block_info; + block_info[0].block_size = 1 << priv->page_2size_log; + block_info[0].blocks = priv->end_page - priv->start_page; + +// diag_printf("\nDF INIT block_size = %d blocks = %d\n", +// block_info[0].block_size, block_info[0].blocks); + + return CYG_FLASH_ERR_OK; +} + +static size_t +df_flash_query(struct cyg_flash_dev *dev, void *data, const size_t len) +{ + return len; +} + +static int +df_flash_erase_block(struct cyg_flash_dev *dev, + const cyg_flashaddr_t base) +{ + cyg_dataflash_flash_dev_config_t *config; + cyg_dataflash_flash_dev_priv_t *priv; + cyg_uint32 page; + + config = (cyg_dataflash_flash_dev_config_t *) dev->config; + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + + page = priv->start_page + + ((base - config->address) >> priv->page_2size_log); + +// diag_printf("\nDF ERASE base = %x page = %d\n", base, page); + + cyg_dataflash_aquire(&priv->dev); + cyg_dataflash_erase(&priv->dev, page, true); + cyg_dataflash_release(&priv->dev); + + return CYG_FLASH_ERR_OK; +} + +static int +df_flash_program(struct cyg_flash_dev *dev, + cyg_flashaddr_t base, + const void *data, + const size_t len) +{ + cyg_dataflash_flash_dev_config_t *config; + cyg_dataflash_flash_dev_priv_t *priv; + cyg_uint32 page; + + config = (cyg_dataflash_flash_dev_config_t *) dev->config; + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + + page = priv->start_page + + ((base - config->address) >> priv->page_2size_log); + +// diag_printf("\nDF PROGRAM base = %x page = %d len = %d\n", base, page, len); + + cyg_dataflash_aquire(&priv->dev); + cyg_dataflash_mem_to_buf(&priv->dev, 1, page, true); + cyg_dataflash_write_buf(&priv->dev, 1, data, len, 0); + cyg_dataflash_program_buf(&priv->dev, 1, page, true, true); + cyg_dataflash_release(&priv->dev); + + return CYG_FLASH_ERR_OK; +} + +static int +df_flash_read(struct cyg_flash_dev *dev, + const cyg_flashaddr_t base, + void *data, + const size_t len) +{ + cyg_dataflash_flash_dev_config_t *config; + cyg_dataflash_flash_dev_priv_t *priv; + cyg_uint32 page; + + config = (cyg_dataflash_flash_dev_config_t *) dev->config; + priv = (cyg_dataflash_flash_dev_priv_t *) dev->priv; + + page = priv->start_page + + ((base - config->address) >> priv->page_2size_log); + +// diag_printf("\nDF READ base = %x page = %d len = %d\n", base, page, len); + + cyg_dataflash_aquire(&priv->dev); + cyg_dataflash_mem_to_buf(&priv->dev, 1, page, true); + cyg_dataflash_read_buf(&priv->dev, 1, data, len, 0); + cyg_dataflash_release(&priv->dev); + + return CYG_FLASH_ERR_OK; +} + +static int +df_flash_hwr_map_error(struct cyg_flash_dev *dev, int err) +{ + return err; +} + +static int +df_flash_block_lock(struct cyg_flash_dev *dev, + const cyg_flashaddr_t block_base) +{ + return CYG_FLASH_ERR_INVALID; +} + +static int +df_flash_block_unlock(struct cyg_flash_dev *dev, + const cyg_flashaddr_t block_base) +{ + return CYG_FLASH_ERR_INVALID; +} + +// -------------------------------------------------------------------------- + +CYG_FLASH_FUNS(cyg_dataflash_flash_dev_funs, + df_flash_init, + df_flash_query, + df_flash_erase_block, + df_flash_program, + df_flash_read, + df_flash_hwr_map_error, + df_flash_block_lock, + df_flash_block_unlock +); + +//---------------------------------------------------------------------------- +// End of devs_flash_atmel_dataflash_flash_dev_funs.c
