summaryrefslogtreecommitdiffstats
path: root/c/src/libchip/i2c/spi-flash-m25p40.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/libchip/i2c/spi-flash-m25p40.c')
-rw-r--r--c/src/libchip/i2c/spi-flash-m25p40.c366
1 files changed, 28 insertions, 338 deletions
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;