summaryrefslogtreecommitdiffstats
path: root/c/src/libchip
diff options
context:
space:
mode:
authorThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-05-15 15:10:38 +0000
committerThomas Doerfler <Thomas.Doerfler@embedded-brains.de>2008-05-15 15:10:38 +0000
commit42bf1b9f13d9269d9a98de4bdc1a11365865ef42 (patch)
treeb0ea837f63ea5ac5d6d04473f492d6329a3ee450 /c/src/libchip
parent2008-05-14 Till Straumann <strauman@slac.stanford.edu> (diff)
downloadrtems-42bf1b9f13d9269d9a98de4bdc1a11365865ef42.tar.bz2
adapted gen83xx to new board
Diffstat (limited to 'c/src/libchip')
-rw-r--r--c/src/libchip/Makefile.am7
-rw-r--r--c/src/libchip/i2c/spi-flash-m25p40.c366
-rw-r--r--c/src/libchip/i2c/spi-flash-m25p40.h2
-rw-r--r--c/src/libchip/i2c/spi-fram-fm25l256.c60
-rw-r--r--c/src/libchip/i2c/spi-fram-fm25l256.h44
-rw-r--r--c/src/libchip/i2c/spi-memdrv.c445
-rw-r--r--c/src/libchip/i2c/spi-memdrv.h90
-rw-r--r--c/src/libchip/preinstall.am8
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)