diff options
author | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-05-15 15:10:38 +0000 |
---|---|---|
committer | Thomas Doerfler <Thomas.Doerfler@embedded-brains.de> | 2008-05-15 15:10:38 +0000 |
commit | 42bf1b9f13d9269d9a98de4bdc1a11365865ef42 (patch) | |
tree | b0ea837f63ea5ac5d6d04473f492d6329a3ee450 /c/src/libchip | |
parent | 2008-05-14 Till Straumann <strauman@slac.stanford.edu> (diff) | |
download | rtems-42bf1b9f13d9269d9a98de4bdc1a11365865ef42.tar.bz2 |
adapted gen83xx to new board
Diffstat (limited to 'c/src/libchip')
-rw-r--r-- | c/src/libchip/Makefile.am | 7 | ||||
-rw-r--r-- | c/src/libchip/i2c/spi-flash-m25p40.c | 366 | ||||
-rw-r--r-- | c/src/libchip/i2c/spi-flash-m25p40.h | 2 | ||||
-rw-r--r-- | c/src/libchip/i2c/spi-fram-fm25l256.c | 60 | ||||
-rw-r--r-- | c/src/libchip/i2c/spi-fram-fm25l256.h | 44 | ||||
-rw-r--r-- | c/src/libchip/i2c/spi-memdrv.c | 445 | ||||
-rw-r--r-- | c/src/libchip/i2c/spi-memdrv.h | 90 | ||||
-rw-r--r-- | c/src/libchip/preinstall.am | 8 |
8 files changed, 681 insertions, 341 deletions
diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am index 243c87d865..fc9da09a96 100644 --- a/c/src/libchip/Makefile.am +++ b/c/src/libchip/Makefile.am @@ -74,13 +74,16 @@ EXTRA_DIST += rtc/README.ds1643 rtc/README.icm7170 rtc/README.m48t08 \ # i2c if LIBCHIP include_libchip_HEADERS += i2c/i2c-ds1621.h i2c/i2c-2b-eeprom.h \ - i2c/spi-flash-m25p40.h + i2c/spi-memdrv.h \ + i2c/spi-flash-m25p40.h i2c/spi-fram-fm25l256.h noinst_LIBRARIES += libi2cio.a libi2cio_a_CPPFLAGS = $(AM_CPPFLAGS) libi2cio_a_SOURCES = i2c/i2c-ds1621.c i2c/i2c-2b-eeprom.c \ i2c/i2c-ds1621.h i2c/i2c-2b-eeprom.h \ - i2c/spi-flash-m25p40.c i2c/spi-flash-m25p40.h + i2c/spi-memdrv.c i2c/spi-memdrv.h \ + i2c/spi-flash-m25p40.c i2c/spi-flash-m25p40.h \ + i2c/spi-fram-fm25l256.c i2c/spi-fram-fm25l256.h endif # serial diff --git a/c/src/libchip/i2c/spi-flash-m25p40.c b/c/src/libchip/i2c/spi-flash-m25p40.c index 782b32f691..4e2e4b9423 100644 --- a/c/src/libchip/i2c/spi-flash-m25p40.c +++ b/c/src/libchip/i2c/spi-flash-m25p40.c @@ -15,11 +15,6 @@ | | +-----------------------------------------------------------------+ \*===============================================================*/ -/* - * FIXME: currently, this driver only supports read/write accesses - * erase accesses are to be completed - */ - #include <rtems.h> #include <rtems/libi2c.h> @@ -27,344 +22,39 @@ #include <libchip/spi-flash-m25p40.h> #include <rtems/libio.h> -#define FLASH_M25P40_CMD_WREN 0x06 -#define FLASH_M25P40_CMD_WRDIS 0x04 -#define FLASH_M25P40_CMD_RDID 0x9F -#define FLASH_M25P40_CMD_RDSR 0x05 -#define FLASH_M25P40_CMD_WRSR 0x01 -#define FLASH_M25P40_CMD_READ 0x03 -#define FLASH_M25P40_CMD_PP 0x02 /* page program */ -#define FLASH_M25P40_CMD_SE 0xD8 /* sector erase */ -#define FLASH_M25P40_CMD_BE 0xC7 /* bulk erase */ -#define FLASH_M25P40_CMD_DP 0xB9 /* deep power down */ -#define FLASH_M25P40_CMD_RES 0xAB /* release from deep power down */ - -#define M25P40_PAGE_SIZE 256 -#define M25P40_TOTAL_SIZE (512*1024) - -const rtems_libi2c_tfr_mode_t spi_flash_m25p40_tfr_mode = { - baudrate: 20000000, /* maximum bits per second */ - bits_per_char: 8, /* how many bits per byte/word/longword? */ - lsb_first: FALSE, /* FALSE: send MSB first */ - clock_inv: FALSE, /* FALSE: non-inverted clock (high active) */ - clock_phs: FALSE /* FALSE: clock starts in middle of data tfr */ -} ; - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_status_code spi_flash_m25p40_wait_ms -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| wait a certain interval given in ms | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - int ms /* time to wait in milliseconds */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - rtems_interval ticks_per_second; - - rc = rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND,&ticks_per_second); - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_task_wake_after(ticks_per_second * ms / 1000); - } - return rc; -} - -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_status_code spi_flash_m25p40_write -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| write a block of data to flash | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, /* major device number */ - rtems_device_major_number minor, /* minor device number */ - void *arg /* ptr to write argument struct */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - rtems_libio_rw_args_t *rwargs = arg; - unsigned off = rwargs->offset; - int cnt = rwargs->count; - unsigned char *buf = (unsigned char *)rwargs->buffer; - int bytes_sent = 0; - int curr_cnt; - unsigned char cmdbuf[4]; - int ret_cnt = 0; - /* - * check arguments - */ - if (rc == RTEMS_SUCCESSFUL) { - if ((cnt <= 0) || - (cnt > M25P40_TOTAL_SIZE) || - (off > (M25P40_TOTAL_SIZE-cnt))) { - rc = RTEMS_INVALID_SIZE; - } - else if (buf == NULL) { - rc = RTEMS_INVALID_ADDRESS; - } - } - /* - * select device, set transfer mode, address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(minor); - } - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = -rtems_libi2c_ioctl(minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &spi_flash_m25p40_tfr_mode); - } - - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(minor,TRUE); - } - - /* - * send write_enable command - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = FLASH_M25P40_CMD_WREN; - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - /* - * terminate transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(minor); - } - while ((rc == RTEMS_SUCCESSFUL) && - (cnt > bytes_sent)) { - curr_cnt = cnt; - if ((off / M25P40_PAGE_SIZE) != - ((off+curr_cnt+1) / M25P40_PAGE_SIZE)) { - curr_cnt = M25P40_PAGE_SIZE - (off % M25P40_PAGE_SIZE); - } - /* - * select device, set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(minor); - } - - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(minor,TRUE); - } - - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = -rtems_libi2c_ioctl(minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &spi_flash_m25p40_tfr_mode); - } - /* - * send "page program" command and address - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = FLASH_M25P40_CMD_PP; - cmdbuf[1] = (off >> 16) & 0xff; - cmdbuf[2] = (off >> 8) & 0xff; - cmdbuf[3] = (off >> 0) & 0xff; - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,4); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - /* - * send write data - */ - if (rc == RTEMS_SUCCESSFUL) { - ret_cnt = rtems_libi2c_write_bytes(minor,buf,curr_cnt); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - /* - * terminate transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(minor); - } - /* - * wait proper time for data to store: 5ms - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = spi_flash_m25p40_wait_ms(5); - } - /* - * adjust bytecount to be sent and pointers - */ - bytes_sent += curr_cnt; - off += curr_cnt; - buf += curr_cnt; - } - rwargs->bytes_moved = bytes_sent; - return rc; -} -/*=========================================================================*\ -| Function: | -\*-------------------------------------------------------------------------*/ -rtems_status_code spi_flash_m25p40_read -( -/*-------------------------------------------------------------------------*\ -| Purpose: | -| read a block of data from flash | -+---------------------------------------------------------------------------+ -| Input Parameters: | -\*-------------------------------------------------------------------------*/ - rtems_device_major_number major, /* major device number */ - rtems_device_major_number minor, /* minor device number */ - void *arg /* ptr to read argument struct */ -) -/*-------------------------------------------------------------------------*\ -| Return Value: | -| o = ok or error code | -\*=========================================================================*/ -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - rtems_libio_rw_args_t *rwargs = arg; - unsigned off = rwargs->offset; - int cnt = rwargs->count; - unsigned char *buf = (unsigned char *)rwargs->buffer; - unsigned char cmdbuf[4]; - int ret_cnt = 0; - /* - * check arguments - */ - if (rc == RTEMS_SUCCESSFUL) { - if ((cnt <= 0) || - (cnt > M25P40_TOTAL_SIZE) || - (off > (M25P40_TOTAL_SIZE-cnt))) { - rc = RTEMS_INVALID_SIZE; - } - else if (buf == NULL) { - rc = RTEMS_INVALID_ADDRESS; - } - } - /* - * select device, set transfer mode, address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_start(minor); - } - /* - * set transfer mode - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = -rtems_libi2c_ioctl(minor, - RTEMS_LIBI2C_IOCTL_SET_TFRMODE, - &spi_flash_m25p40_tfr_mode); - } - /* - * address device - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_addr(minor,TRUE); - } - - if (off >= M25P40_TOTAL_SIZE) { - /* - * HACK: beyond size of Flash array? then read status register instead - */ - /* - * send read status register command - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = FLASH_M25P40_CMD_RDSR; - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - } - else { - /* - * send read command and address - */ - if (rc == RTEMS_SUCCESSFUL) { - cmdbuf[0] = FLASH_M25P40_CMD_READ; - cmdbuf[1] = (off >> 16) & 0xff; - cmdbuf[2] = (off >> 8) & 0xff; - cmdbuf[3] = (off >> 0) & 0xff; - ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,4); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - } - /* - * fetch read data - */ - if (rc == RTEMS_SUCCESSFUL) { - ret_cnt = rtems_libi2c_read_bytes (minor,buf,cnt); - if (ret_cnt < 0) { - rc = -ret_cnt; - } - } - - /* - * terminate transfer - */ - if (rc == RTEMS_SUCCESSFUL) { - rc = rtems_libi2c_send_stop(minor); +static spi_memdrv_t spi_flash_m25p40_rw_drv_t = { + {/* public fields */ + ops: &spi_memdrv_rw_ops, /* operations of general memdrv */ + size: sizeof (spi_flash_m25p40_rw_drv_t), + }, + { /* our private fields */ + baudrate: 2000000, + erase_before_program: TRUE, + empty_state: 0xff, + page_size: 256, /* programming page size in byte */ + sector_size: 64*1024, /* erase sector size in byte */ + mem_size: 512*1024 /* total capacity in byte */ } - rwargs->bytes_moved = (rc == RTEMS_SUCCESSFUL) ? ret_cnt : 0; - - return rc; -} - -static rtems_driver_address_table spi_flash_m25p40_rw_ops = { - read_entry: spi_flash_m25p40_read, - write_entry: spi_flash_m25p40_write -}; - -static rtems_libi2c_drv_t spi_flash_m25p40_rw_drv_tbl = { - ops: &spi_flash_m25p40_rw_ops, - size: sizeof (spi_flash_m25p40_rw_drv_tbl), }; rtems_libi2c_drv_t *spi_flash_m25p40_rw_driver_descriptor = -&spi_flash_m25p40_rw_drv_tbl; - -static rtems_driver_address_table spi_flash_m25p40_ro_ops = { - read_entry: spi_flash_m25p40_read, -}; - -static rtems_libi2c_drv_t spi_flash_m25p40_ro_drv_tbl = { - ops: &spi_flash_m25p40_ro_ops, - size: sizeof (spi_flash_m25p40_ro_drv_tbl), +&spi_flash_m25p40_rw_drv_t.libi2c_drv_entry; + +static spi_memdrv_t spi_flash_m25p40_ro_drv_t = { + {/* public fields */ + ops: &spi_memdrv_ro_ops, /* operations of general memdrv */ + size: sizeof (spi_flash_m25p40_ro_drv_t), + }, + { /* our private fields */ + baudrate: 2000000, + erase_before_program: TRUE, + empty_state: 0xff, + page_size: 256, /* programming page size in byte */ + sector_size: 64*1024, /* erase sector size in byte */ + mem_size: 512*1024 /* total capacity in byte */ + } }; rtems_libi2c_drv_t *spi_flash_m25p40_ro_driver_descriptor = -&spi_flash_m25p40_ro_drv_tbl; +&spi_flash_m25p40_ro_drv_t.libi2c_drv_entry; diff --git a/c/src/libchip/i2c/spi-flash-m25p40.h b/c/src/libchip/i2c/spi-flash-m25p40.h index 26aa37e6f1..f653c125e0 100644 --- a/c/src/libchip/i2c/spi-flash-m25p40.h +++ b/c/src/libchip/i2c/spi-flash-m25p40.h @@ -24,7 +24,7 @@ #ifndef _LIBCHIP_SPI_FLASH_M25P40_H #define _LIBCHIP_SPI_FLASH_M25P40_H -#include <rtems/libi2c.h> +#include <libchip/spi-memdrv.h> #ifdef __cplusplus extern "C" { diff --git a/c/src/libchip/i2c/spi-fram-fm25l256.c b/c/src/libchip/i2c/spi-fram-fm25l256.c new file mode 100644 index 0000000000..b09e97154b --- /dev/null +++ b/c/src/libchip/i2c/spi-fram-fm25l256.c @@ -0,0 +1,60 @@ +/*===============================================================*\ +| Project: SPI driver for FM25L256 like spi fram device | ++-----------------------------------------------------------------+ +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +\*===============================================================*/ + +#include <rtems.h> +#include <rtems/libi2c.h> + +#include <libchip/spi-fram-fm25l256.h> +#include <rtems/libio.h> + + +static spi_memdrv_t spi_fram_fm25l256_rw_drv_t = { + {/* public fields */ + ops: &spi_memdrv_rw_ops, /* operations of general memdrv */ + size: sizeof (spi_fram_fm25l256_rw_drv_t), + }, + { /* our private fields */ + baudrate: 2000000, + erase_before_program: FALSE, + empty_state: 0xff, + page_size: 32*1024, /* programming page size in byte */ + sector_size: 1, /* erase sector size in byte */ + mem_size: 32*1024 /* total capacity in byte */ + } +}; + +rtems_libi2c_drv_t *spi_fram_fm25l256_rw_driver_descriptor = +&spi_fram_fm25l256_rw_drv_t.libi2c_drv_entry; + +static spi_memdrv_t spi_fram_fm25l256_ro_drv_t = { + {/* public fields */ + ops: &spi_memdrv_ro_ops, /* operations of general memdrv */ + size: sizeof (spi_fram_fm25l256_ro_drv_t), + }, + { /* our private fields */ + baudrate: 2000000, + erase_before_program: FALSE, + empty_state: 0xff, + page_size: 32*1024, /* programming page size in byte */ + sector_size: 1, /* erase sector size in byte */ + mem_size: 32*1024 /* total capacity in byte */ + } +}; + +rtems_libi2c_drv_t *spi_fram_fm25l256_ro_driver_descriptor = +&spi_fram_fm25l256_ro_drv_t.libi2c_drv_entry; diff --git a/c/src/libchip/i2c/spi-fram-fm25l256.h b/c/src/libchip/i2c/spi-fram-fm25l256.h new file mode 100644 index 0000000000..d2287c1c14 --- /dev/null +++ b/c/src/libchip/i2c/spi-fram-fm25l256.h @@ -0,0 +1,44 @@ +/*===============================================================*\ +| Project: SPI driver for FM25L256 like spi fram device | ++-----------------------------------------------------------------+ +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +\*===============================================================*/ +/* + * FIXME: currently, this driver only supports read/write accesses + * erase accesses are to be completed + */ + + +#ifndef _LIBCHIP_SPI_FRAM_FM25L256_H +#define _LIBCHIP_SPI_FRAM_FM25L256_H + +#include <libchip/spi-memdrv.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * pass one of these descriptor pointers to rtems_libi2c_register_drv + */ +extern rtems_libi2c_drv_t *spi_fram_fm25l256_rw_driver_descriptor; + +extern rtems_libi2c_drv_t *spi_fram_fm25l256_ro_driver_descriptor; + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBCHIP_SPI_FRAM_FM25L256_H */ diff --git a/c/src/libchip/i2c/spi-memdrv.c b/c/src/libchip/i2c/spi-memdrv.c new file mode 100644 index 0000000000..106a02cacc --- /dev/null +++ b/c/src/libchip/i2c/spi-memdrv.c @@ -0,0 +1,445 @@ +/*===============================================================*\ +| Project: SPI driver for spi memory devices | ++-----------------------------------------------------------------+ +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +\*===============================================================*/ +/* + * FIXME: currently, this driver only supports read/write accesses + * erase accesses are to be completed + */ + + +#include <rtems.h> +#include <rtems/libi2c.h> + +#include <libchip/spi-memdrv.h> +#include <rtems/libio.h> + +#define SPI_MEM_CMD_WREN 0x06 +#define SPI_MEM_CMD_WRDIS 0x04 +#define SPI_MEM_CMD_RDID 0x9F +#define SPI_MEM_CMD_RDSR 0x05 +#define SPI_MEM_CMD_WRSR 0x01 +#define SPI_MEM_CMD_READ 0x03 +#define SPI_MEM_CMD_PP 0x02 /* page program */ +#define SPI_MEM_CMD_SE 0xD8 /* sector erase */ +#define SPI_MEM_CMD_BE 0xC7 /* bulk erase */ +#define SPI_MEM_CMD_DP 0xB9 /* deep power down */ +#define SPI_MEM_CMD_RES 0xAB /* release from deep power down */ + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_status_code spi_memdrv_minor2param_ptr +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| translate given minor device number to param pointer | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_minor_number minor, /* minor number of device */ + spi_memdrv_param_t **param_ptr /* ptr to param ptr */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| o = ok or error code | +\*=========================================================================*/ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + spi_memdrv_t *drv_ptr; + + if (rc == RTEMS_SUCCESSFUL) { + rc = -rtems_libi2c_ioctl(minor, + RTEMS_LIBI2C_IOCTL_GET_DRV_T, + &drv_ptr); + } + if ((rc == RTEMS_SUCCESSFUL) && + (drv_ptr->libi2c_drv_entry.size != sizeof(spi_memdrv_t))) { + rc = RTEMS_INVALID_SIZE; + } + if (rc == RTEMS_SUCCESSFUL) { + *param_ptr = &(drv_ptr->spi_memdrv_param); + } + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_status_code spi_memdrv_wait_ms +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| wait a certain interval given in ms | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + int ms /* time to wait in milliseconds */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| o = ok or error code | +\*=========================================================================*/ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + rtems_interval ticks_per_second; + + rc = rtems_clock_get(RTEMS_CLOCK_GET_TICKS_PER_SECOND,&ticks_per_second); + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_task_wake_after(ticks_per_second * ms / 1000); + } + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_status_code spi_memdrv_write +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| write a block of data to flash | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, /* major device number */ + rtems_device_minor_number minor, /* minor device number */ + void *arg /* ptr to write argument struct */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| o = ok or error code | +\*=========================================================================*/ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + rtems_libio_rw_args_t *rwargs = arg; + unsigned off = rwargs->offset; + int cnt = rwargs->count; + unsigned char *buf = (unsigned char *)rwargs->buffer; + int bytes_sent = 0; + int curr_cnt; + unsigned char cmdbuf[4]; + int ret_cnt = 0; + int cmd_size; + spi_memdrv_param_t *mem_param_ptr; + rtems_libi2c_tfr_mode_t tfr_mode = { + baudrate: 20000000, /* maximum bits per second */ + bits_per_char: 8, /* how many bits per byte/word/longword? */ + lsb_first: FALSE, /* FALSE: send MSB first */ + clock_inv: FALSE, /* FALSE: non-inverted clock (high active) */ + clock_phs: FALSE /* FALSE: clock starts in middle of data tfr */ + } ; + + /* + * get mem parameters + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = spi_memdrv_minor2param_ptr(minor,&mem_param_ptr); + } + /* + * check arguments + */ + if (rc == RTEMS_SUCCESSFUL) { + if ((cnt <= 0) || + (cnt > mem_param_ptr->mem_size) || + (off > (mem_param_ptr->mem_size-cnt))) { + rc = RTEMS_INVALID_SIZE; + } + else if (buf == NULL) { + rc = RTEMS_INVALID_ADDRESS; + } + } + while ((rc == RTEMS_SUCCESSFUL) && + (cnt > bytes_sent)) { + curr_cnt = cnt; + if ((mem_param_ptr->page_size > 0) && + (off / mem_param_ptr->page_size) != + ((off+curr_cnt+1) / mem_param_ptr->page_size)) { + curr_cnt = mem_param_ptr->page_size - (off % mem_param_ptr->page_size); + } + /* + * select device, set transfer mode, address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_start(minor); + } + /* + * set transfer mode + */ + if (rc == RTEMS_SUCCESSFUL) { + tfr_mode.baudrate = mem_param_ptr->baudrate; + rc = -rtems_libi2c_ioctl(minor, + RTEMS_LIBI2C_IOCTL_SET_TFRMODE, + &tfr_mode); + } + + /* + * address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_addr(minor,TRUE); + } + + /* + * send write_enable command + */ + if (rc == RTEMS_SUCCESSFUL) { + cmdbuf[0] = SPI_MEM_CMD_WREN; + ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + /* + * terminate transfer + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_stop(minor); + } + /* + * select device, set transfer mode + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_start(minor); + } + + /* + * address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_addr(minor,TRUE); + } + + /* + * set transfer mode + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = -rtems_libi2c_ioctl(minor, + RTEMS_LIBI2C_IOCTL_SET_TFRMODE, + &tfr_mode); + } + /* + * send "page program" command and address + */ + if (rc == RTEMS_SUCCESSFUL) { + cmdbuf[0] = SPI_MEM_CMD_PP; + if (mem_param_ptr->mem_size > 256*256) { + cmdbuf[1] = (off >> 16) & 0xff; + cmdbuf[2] = (off >> 8) & 0xff; + cmdbuf[3] = (off >> 0) & 0xff; + cmd_size = 4; + } + else if (mem_param_ptr->mem_size > 256) { + cmdbuf[1] = (off >> 8) & 0xff; + cmdbuf[2] = (off >> 0) & 0xff; + cmd_size = 3; + } + else { + cmdbuf[1] = (off >> 0) & 0xff; + cmd_size = 1; + } + + ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,cmd_size); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + /* + * send write data + */ + if (rc == RTEMS_SUCCESSFUL) { + ret_cnt = rtems_libi2c_write_bytes(minor,buf,curr_cnt); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + /* + * terminate transfer + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_stop(minor); + } + /* + * wait proper time for data to store: 5ms + * FIXME: select proper interval or poll, until device is finished + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = spi_memdrv_wait_ms(5); + } + /* + * adjust bytecount to be sent and pointers + */ + bytes_sent += curr_cnt; + off += curr_cnt; + buf += curr_cnt; + } + rwargs->bytes_moved = bytes_sent; + return rc; +} + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_status_code spi_memdrv_read +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| read a block of data from flash | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, /* major device number */ + rtems_device_minor_number minor, /* minor device number */ + void *arg /* ptr to read argument struct */ +) +/*-------------------------------------------------------------------------*\ +| Return Value: | +| o = ok or error code | +\*=========================================================================*/ +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + rtems_libio_rw_args_t *rwargs = arg; + unsigned off = rwargs->offset; + int cnt = rwargs->count; + unsigned char *buf = (unsigned char *)rwargs->buffer; + unsigned char cmdbuf[4]; + int ret_cnt = 0; + int cmd_size; + spi_memdrv_param_t *mem_param_ptr; + rtems_libi2c_tfr_mode_t tfr_mode = { + baudrate: 20000000, /* maximum bits per second */ + bits_per_char: 8, /* how many bits per byte/word/longword? */ + lsb_first: FALSE, /* FALSE: send MSB first */ + clock_inv: FALSE, /* FALSE: non-inverted clock (high active) */ + clock_phs: FALSE /* FALSE: clock starts in middle of data tfr */ + } ; + + /* + * get mem parameters + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = spi_memdrv_minor2param_ptr(minor,&mem_param_ptr); + } + /* + * check arguments + */ + if (rc == RTEMS_SUCCESSFUL) { + if ((cnt <= 0) || + (cnt > mem_param_ptr->mem_size) || + (off > (mem_param_ptr->mem_size-cnt))) { + rc = RTEMS_INVALID_SIZE; + } + else if (buf == NULL) { + rc = RTEMS_INVALID_ADDRESS; + } + } + /* + * select device, set transfer mode, address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_start(minor); + } + /* + * set transfer mode + */ + if (rc == RTEMS_SUCCESSFUL) { + tfr_mode.baudrate = mem_param_ptr->baudrate; + rc = -rtems_libi2c_ioctl(minor, + RTEMS_LIBI2C_IOCTL_SET_TFRMODE, + &tfr_mode); + } + /* + * address device + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_addr(minor,TRUE); + } + + if (off >= mem_param_ptr->mem_size) { + /* + * HACK: beyond size of memory array? then read status register instead + */ + /* + * send read status register command + */ + if (rc == RTEMS_SUCCESSFUL) { + cmdbuf[0] = SPI_MEM_CMD_RDSR; + ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,1); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + } + else { + /* + * send read command and address + */ + if (rc == RTEMS_SUCCESSFUL) { + cmdbuf[0] = SPI_MEM_CMD_READ; + if (mem_param_ptr->mem_size > 256*256) { + cmdbuf[1] = (off >> 16) & 0xff; + cmdbuf[2] = (off >> 8) & 0xff; + cmdbuf[3] = (off >> 0) & 0xff; + cmd_size = 4; + } + else if (mem_param_ptr->mem_size > 256) { + cmdbuf[1] = (off >> 8) & 0xff; + cmdbuf[2] = (off >> 0) & 0xff; + cmd_size = 3; + } + else { + cmdbuf[1] = (off >> 0) & 0xff; + cmd_size = 1; + } + ret_cnt = rtems_libi2c_write_bytes(minor,cmdbuf,cmd_size); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + } + /* + * fetch read data + */ + if (rc == RTEMS_SUCCESSFUL) { + ret_cnt = rtems_libi2c_read_bytes (minor,buf,cnt); + if (ret_cnt < 0) { + rc = -ret_cnt; + } + } + + /* + * terminate transfer + */ + if (rc == RTEMS_SUCCESSFUL) { + rc = rtems_libi2c_send_stop(minor); + } + rwargs->bytes_moved = (rc == RTEMS_SUCCESSFUL) ? ret_cnt : 0; + + return rc; +} + +/* + * driver operation tables + */ +rtems_driver_address_table spi_memdrv_rw_ops = { + read_entry: spi_memdrv_read, + write_entry: spi_memdrv_write +}; + +rtems_driver_address_table spi_memdrv_ro_ops = { + read_entry: spi_memdrv_read, +}; + diff --git a/c/src/libchip/i2c/spi-memdrv.h b/c/src/libchip/i2c/spi-memdrv.h new file mode 100644 index 0000000000..fb95b3dd4f --- /dev/null +++ b/c/src/libchip/i2c/spi-memdrv.h @@ -0,0 +1,90 @@ +/*===============================================================*\ +| Project: SPI driver for spi memory devices | ++-----------------------------------------------------------------+ +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.com/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +\*===============================================================*/ + + +#ifndef _LIBCHIP_SPI_MEMDRV_H +#define _LIBCHIP_SPI_MEMDRV_H + +#include <rtems/libi2c.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_status_code spi_memdrv_write +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| write a block of data to memory | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, /* major device number */ + rtems_device_major_number minor, /* minor device number */ + void *arg /* ptr to write argument struct */ + ); +/*-------------------------------------------------------------------------*\ +| Return Value: | +| o = ok or error code | +\*=========================================================================*/ + +/*=========================================================================*\ +| Function: | +\*-------------------------------------------------------------------------*/ +rtems_status_code spi_memdrv_read +( +/*-------------------------------------------------------------------------*\ +| Purpose: | +| read a block of data from memory | ++---------------------------------------------------------------------------+ +| Input Parameters: | +\*-------------------------------------------------------------------------*/ + rtems_device_major_number major, /* major device number */ + rtems_device_major_number minor, /* minor device number */ + void *arg /* ptr to read argument struct */ + ); +/*-------------------------------------------------------------------------*\ +| Return Value: | +| o = ok or error code | +\*=========================================================================*/ + + typedef struct { + uint32_t baudrate; /* tfr rate, bits per second */ + boolean erase_before_program; + uint32_t empty_state; /* value of erased cells */ + uint32_t page_size; /* programming page size in byte */ + uint32_t sector_size; /* erase sector size in byte */ + uint32_t mem_size /* total capacity in byte */ + } spi_memdrv_param_t; + + typedef struct { + rtems_libi2c_drv_t libi2c_drv_entry; /* general i2c/spi params */ + spi_memdrv_param_t spi_memdrv_param; /* private parameters */ + } spi_memdrv_t; + + extern rtems_driver_address_table spi_memdrv_rw_ops; + extern rtems_driver_address_table spi_memdrv_ro_ops; + +#ifdef __cplusplus +} +#endif + +#endif /* _LIBCHIP_SPI_MEMDRV_H */ diff --git a/c/src/libchip/preinstall.am b/c/src/libchip/preinstall.am index d12e43e345..d7d7824bd8 100644 --- a/c/src/libchip/preinstall.am +++ b/c/src/libchip/preinstall.am @@ -125,9 +125,17 @@ $(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h: i2c/i2c-2b-eeprom.h $(PROJECT_INCLUD $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/i2c-2b-eeprom.h +$(PROJECT_INCLUDE)/libchip/spi-memdrv.h: i2c/spi-memdrv.h $(PROJECT_INCLUDE)/libchip/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/spi-memdrv.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/spi-memdrv.h + $(PROJECT_INCLUDE)/libchip/spi-flash-m25p40.h: i2c/spi-flash-m25p40.h $(PROJECT_INCLUDE)/libchip/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/spi-flash-m25p40.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/spi-flash-m25p40.h + +$(PROJECT_INCLUDE)/libchip/spi-fram-fm25l256.h: i2c/spi-fram-fm25l256.h $(PROJECT_INCLUDE)/libchip/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libchip/spi-fram-fm25l256.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/libchip/spi-fram-fm25l256.h endif if LIBCHIP $(PROJECT_INCLUDE)/libchip/mc68681.h: serial/mc68681.h $(PROJECT_INCLUDE)/libchip/$(dirstamp) |