mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 13:27:01 +08:00
drivers: mtd: fix nxstyle errors
Fix nxstyle errors to pass the CI errors. Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
This commit is contained in:
committed by
Xiang Xiao
parent
95adb15824
commit
2d8b193df4
+114
-82
@@ -1,6 +1,7 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/at24xx.c
|
* drivers/mtd/at24xx.c
|
||||||
* Driver for I2C-based at24cxx EEPROM(at24c32,at24c64,at24c128,at24c256,at24c512)
|
* Driver for I2C-based at24cxx EEPROM
|
||||||
|
* (at24c32,at24c64,at24c128,at24c256,at24c512)
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
|
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
|
||||||
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
|
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
|
||||||
@@ -40,11 +41,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
@@ -66,11 +67,13 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_MTD_AT24XX
|
#ifdef CONFIG_MTD_AT24XX
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* As a minimum, the size of the AT24 part and its 7-bit I2C address are required. */
|
/* As a minimum,
|
||||||
|
* the size of the AT24 part and its 7-bit I2C address are required.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_AT24XX_SIZE
|
#ifndef CONFIG_AT24XX_SIZE
|
||||||
# warning "Assuming AT24 size 64"
|
# warning "Assuming AT24 size 64"
|
||||||
@@ -129,11 +132,11 @@
|
|||||||
# define AT24XX_ADDRSIZE 2
|
# define AT24XX_ADDRSIZE 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* For applications where a file system is used on the AT24, the tiny page sizes
|
/* For applications where a file system is used on the AT24, the tiny page
|
||||||
* will result in very inefficient FLASH usage. In such cases, it is better if
|
* sizes will result in very inefficient FLASH usage. In such cases, it is
|
||||||
* blocks are comprised of "clusters" of pages so that the file system block
|
* better if blocks are comprised of "clusters" of pages so that the file
|
||||||
* size is, say, 256 or 512 bytes. In any event, the block size *must* be an
|
* system block size is, say, 256 or 512 bytes.
|
||||||
* even multiple of the pages.
|
* In any event, the block size *must* be an even multiple of the pages.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_AT24XX_MTD_BLOCKSIZE
|
#ifndef CONFIG_AT24XX_MTD_BLOCKSIZE
|
||||||
@@ -145,9 +148,9 @@
|
|||||||
# define CONFIG_AT24XX_TIMEOUT_MS 10
|
# define CONFIG_AT24XX_TIMEOUT_MS 10
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
||||||
* must appear at the beginning of the definition so that you can freely
|
* must appear at the beginning of the definition so that you can freely
|
||||||
@@ -167,24 +170,33 @@ struct at24c_dev_s
|
|||||||
uint16_t npages; /* 128, 256, 512, 1024 */
|
uint16_t npages; /* 128, 256, 512, 1024 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int at24c_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
static int at24c_erase(FAR struct mtd_dev_s *dev,
|
||||||
static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
off_t startblock,
|
||||||
|
size_t nblocks);
|
||||||
|
static ssize_t at24c_bread(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf);
|
size_t nblocks, FAR uint8_t *buf);
|
||||||
static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
size_t nblocks, FAR const uint8_t *buf);
|
off_t startblock,
|
||||||
static ssize_t at24c_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
size_t nblocks,
|
||||||
|
FAR const uint8_t *buf);
|
||||||
|
static ssize_t at24c_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int at24c_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_AT24XX_MULTI
|
#ifndef CONFIG_AT24XX_MULTI
|
||||||
/* If only a signal AT24 part is supported then a statically allocated state
|
/* If only a signal AT24 part is supported then a statically allocated state
|
||||||
@@ -194,17 +206,17 @@ static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
|||||||
static struct at24c_dev_s g_at24c;
|
static struct at24c_dev_s g_at24c;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_i2c_write
|
* Name: at24c_i2c_write
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Write to the I2C device.
|
* Write to the I2C device.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int at24c_i2c_write(FAR struct at24c_dev_s *priv, uint16_t at24addr,
|
static int at24c_i2c_write(FAR struct at24c_dev_s *priv, uint16_t at24addr,
|
||||||
FAR const uint8_t *buffer, int buflen)
|
FAR const uint8_t *buffer, int buflen)
|
||||||
@@ -224,13 +236,13 @@ static int at24c_i2c_write(FAR struct at24c_dev_s *priv, uint16_t at24addr,
|
|||||||
return I2C_TRANSFER(priv->dev, &msg, 1);
|
return I2C_TRANSFER(priv->dev, &msg, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_i2c_read
|
* Name: at24c_i2c_read
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Read from the I2C device.
|
* Read from the I2C device.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int at24c_i2c_read(FAR struct at24c_dev_s *priv, uint16_t at24addr,
|
static int at24c_i2c_read(FAR struct at24c_dev_s *priv, uint16_t at24addr,
|
||||||
FAR uint8_t *buffer, int buflen)
|
FAR uint8_t *buffer, int buflen)
|
||||||
@@ -250,9 +262,9 @@ static int at24c_i2c_read(FAR struct at24c_dev_s *priv, uint16_t at24addr,
|
|||||||
return I2C_TRANSFER(priv->dev, &msg, 1);
|
return I2C_TRANSFER(priv->dev, &msg, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_eraseall
|
* Name: at24c_eraseall
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int at24c_eraseall(FAR struct at24c_dev_s *priv)
|
static int at24c_eraseall(FAR struct at24c_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -277,7 +289,10 @@ static int at24c_eraseall(FAR struct at24c_dev_s *priv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
wait = CONFIG_AT24XX_TIMEOUT_MS;
|
wait = CONFIG_AT24XX_TIMEOUT_MS;
|
||||||
while (at24c_i2c_write(priv, at24addr, buf, AT24XX_ADDRSIZE) < 0)
|
while (at24c_i2c_write(priv,
|
||||||
|
at24addr,
|
||||||
|
buf,
|
||||||
|
AT24XX_ADDRSIZE) < 0)
|
||||||
{
|
{
|
||||||
finfo("wait\n");
|
finfo("wait\n");
|
||||||
if (!wait--)
|
if (!wait--)
|
||||||
@@ -288,29 +303,36 @@ static int at24c_eraseall(FAR struct at24c_dev_s *priv)
|
|||||||
nxsig_usleep(1000);
|
nxsig_usleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
at24c_i2c_write(priv, at24addr, buf, AT24XX_PAGESIZE + AT24XX_ADDRSIZE);
|
at24c_i2c_write(priv,
|
||||||
|
at24addr,
|
||||||
|
buf,
|
||||||
|
AT24XX_PAGESIZE + AT24XX_ADDRSIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_erase
|
* Name: at24c_erase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int at24c_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
static int at24c_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
/* EEprom need not erase */
|
/* EEprom need not erase */
|
||||||
|
|
||||||
return (int)nblocks;
|
return (int)nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_read_internal
|
* Name: at24c_read_internal
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t at24c_read_internal(FAR struct at24c_dev_s *priv, off_t offset,
|
static ssize_t at24c_read_internal(FAR struct at24c_dev_s *priv,
|
||||||
size_t nbytes, FAR uint8_t *buffer,
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
|
FAR uint8_t *buffer,
|
||||||
uint8_t address)
|
uint8_t address)
|
||||||
{
|
{
|
||||||
uint8_t buf[AT24XX_ADDRSIZE];
|
uint8_t buf[AT24XX_ADDRSIZE];
|
||||||
@@ -363,9 +385,9 @@ static ssize_t at24c_read_internal(FAR struct at24c_dev_s *priv, off_t offset,
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_bread
|
* Name: at24c_bread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buffer)
|
size_t nblocks, FAR uint8_t *buffer)
|
||||||
@@ -421,12 +443,12 @@ static ssize_t at24c_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_bwrite
|
* Name: at24c_bwrite
|
||||||
*
|
*
|
||||||
* Operates on MTD block's and translates to FLASH pages
|
* Operates on MTD block's and translates to FLASH pages
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks,
|
size_t nblocks,
|
||||||
@@ -495,18 +517,22 @@ static ssize_t at24c_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_read
|
* Name: at24c_read
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t at24c_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t at24c_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct at24c_dev_s *priv = (FAR struct at24c_dev_s *)dev;
|
FAR struct at24c_dev_s *priv = (FAR struct at24c_dev_s *)dev;
|
||||||
size_t memsize;
|
size_t memsize;
|
||||||
uint8_t addr;
|
uint8_t addr;
|
||||||
|
|
||||||
finfo("offset: %lu nbytes: %lu\n", (unsigned long)offset, (unsigned long)nbytes);
|
finfo("offset: %lu nbytes: %lu\n",
|
||||||
|
(unsigned long)offset,
|
||||||
|
(unsigned long)nbytes);
|
||||||
|
|
||||||
/* Don't permit reads beyond the end of the memory region */
|
/* Don't permit reads beyond the end of the memory region */
|
||||||
|
|
||||||
@@ -543,9 +569,9 @@ static ssize_t at24c_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes
|
|||||||
return at24c_read_internal(priv, offset, nbytes, buffer, addr);
|
return at24c_read_internal(priv, offset, nbytes, buffer, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_ioctl
|
* Name: at24c_ioctl
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@@ -562,25 +588,28 @@ static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
((uintptr_t)arg);
|
((uintptr_t)arg);
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an array
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* of fixed size blocks.
|
||||||
* appear so.
|
* That is most likely not true, but the client will expect the
|
||||||
|
* device logic to do whatever is necessary to make it appear
|
||||||
|
* so.
|
||||||
*
|
*
|
||||||
* blocksize:
|
* blocksize:
|
||||||
* May be user defined. The block size for the at24XX devices may be
|
* May be user defined.
|
||||||
* larger than the page size in order to better support file systems.
|
* The block size for the at24XX devices may be larger than
|
||||||
* The read and write functions translate BLOCKS to pages for the
|
* the page size in order to better support file systems.
|
||||||
* small flash devices
|
* The read and write functions translate BLOCKS to pages
|
||||||
|
* for the small flash devices
|
||||||
* erasesize:
|
* erasesize:
|
||||||
* It has to be at least as big as the blocksize, bigger serves no
|
* It has to be at least as big as the blocksize, bigger
|
||||||
* purpose.
|
* serves no purpose.
|
||||||
* neraseblocks
|
* neraseblocks
|
||||||
* Note that the device size is in kilobits and must be scaled by
|
* Note that the device size is in kilobits and must be
|
||||||
* 1024 / 8
|
* scaled by 1024 / 8
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if CONFIG_AT24XX_MTD_BLOCKSIZE > AT24XX_PAGESIZE
|
#if CONFIG_AT24XX_MTD_BLOCKSIZE > AT24XX_PAGESIZE
|
||||||
@@ -622,22 +651,24 @@ static int at24c_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_initialize
|
* Name: at24c_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Create an initialized MTD device instance. MTD devices are not registered
|
* Create an initialized MTD device instance.
|
||||||
* in the file system, but are created as instances that can be bound to
|
* MTD devices are not registered in the file system, but are created
|
||||||
* other functions (such as a block or character driver front end).
|
* as instances that can be bound to other functions
|
||||||
|
* (such as a block or character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_AT24XX_MULTI
|
#ifdef CONFIG_AT24XX_MULTI
|
||||||
FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_master_s *dev, uint8_t address)
|
FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_master_s *dev,
|
||||||
|
uint8_t address)
|
||||||
#else
|
#else
|
||||||
FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_master_s *dev)
|
FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_master_s *dev)
|
||||||
#endif
|
#endif
|
||||||
@@ -650,8 +681,8 @@ FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_master_s *dev)
|
|||||||
/* Allocate a state structure (we allocate the structure instead of using
|
/* Allocate a state structure (we allocate the structure instead of using
|
||||||
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
||||||
* The current implementation would handle only one FLASH part per I2C
|
* The current implementation would handle only one FLASH part per I2C
|
||||||
* device (only because of the SPIDEV_FLASH(0) definition) and so would have
|
* device (only because of the SPIDEV_FLASH(0) definition) and so would
|
||||||
* to be extended to handle multiple FLASH parts on the same I2C bus.
|
* have to be extended to handle multiple FLASH parts on the same I2C bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv = (FAR struct at24c_dev_s *)kmm_zalloc(sizeof(struct at24c_dev_s));
|
priv = (FAR struct at24c_dev_s *)kmm_zalloc(sizeof(struct at24c_dev_s));
|
||||||
@@ -664,8 +695,8 @@ FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_master_s *dev)
|
|||||||
#else
|
#else
|
||||||
finfo("dev: %p\n", dev);
|
finfo("dev: %p\n", dev);
|
||||||
|
|
||||||
/* If only a signal AT24 part is supported then a statically allocated state
|
/* If only a signal AT24 part is supported then a statically allocated
|
||||||
* structure is used.
|
* state structure is used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv = &g_at24c;
|
priv = &g_at24c;
|
||||||
@@ -703,14 +734,15 @@ FAR struct mtd_dev_s *at24c_initialize(FAR struct i2c_master_s *dev)
|
|||||||
return (FAR struct mtd_dev_s *)priv;
|
return (FAR struct mtd_dev_s *)priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at24c_uninitialize
|
* Name: at24c_uninitialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Release resources held by an allocated MTD device instance. Resources are only
|
* Release resources held by an allocated MTD device instance.
|
||||||
* allocated for the case where multiple AT24xx devices are support.
|
* Resources are only allocated for the case where multiple AT24xx
|
||||||
|
* devices are support.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_AT24XX_MULTI
|
#ifdef CONFIG_AT24XX_MULTI
|
||||||
void at24c_uninitialize(FAR struct mtd_dev_s *mtd)
|
void at24c_uninitialize(FAR struct mtd_dev_s *mtd)
|
||||||
|
|||||||
+108
-78
@@ -1,4 +1,4 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/at25.c
|
* drivers/mtd/at25.c
|
||||||
* Driver for SPI-based AT25DF321 (32Mbit) flash.
|
* Driver for SPI-based AT25DF321 (32Mbit) flash.
|
||||||
*
|
*
|
||||||
@@ -33,11 +33,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
#include <nuttx/spi/spi.h>
|
#include <nuttx/spi/spi.h>
|
||||||
#include <nuttx/mtd/mtd.h>
|
#include <nuttx/mtd/mtd.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Configuration ********************************************************************/
|
/* Configuration ************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_AT25_SPIMODE
|
#ifndef CONFIG_AT25_SPIMODE
|
||||||
# define CONFIG_AT25_SPIMODE SPIDEV_MODE0
|
# define CONFIG_AT25_SPIMODE SPIDEV_MODE0
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
# define CONFIG_AT25_SPIFREQUENCY 20000000
|
# define CONFIG_AT25_SPIFREQUENCY 20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* AT25 Registers *******************************************************************/
|
/* AT25 Registers ***********************************************************/
|
||||||
|
|
||||||
/* Identification register values */
|
/* Identification register values */
|
||||||
|
|
||||||
@@ -129,9 +129,9 @@
|
|||||||
|
|
||||||
#define AT25_DUMMY 0xa5
|
#define AT25_DUMMY 0xa5
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
||||||
* must appear at the beginning of the definition so that you can freely
|
* must appear at the beginning of the definition so that you can freely
|
||||||
@@ -148,9 +148,9 @@ struct at25_dev_s
|
|||||||
uint32_t npages; /* 32,768 or 65,536 */
|
uint32_t npages; /* 32,768 or 65,536 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
|
|
||||||
@@ -159,29 +159,41 @@ static inline void at25_unlock(FAR struct spi_dev_s *dev);
|
|||||||
static inline int at25_readid(struct at25_dev_s *priv);
|
static inline int at25_readid(struct at25_dev_s *priv);
|
||||||
static void at25_waitwritecomplete(struct at25_dev_s *priv);
|
static void at25_waitwritecomplete(struct at25_dev_s *priv);
|
||||||
static void at25_writeenable(struct at25_dev_s *priv);
|
static void at25_writeenable(struct at25_dev_s *priv);
|
||||||
static inline void at25_sectorerase(struct at25_dev_s *priv, off_t offset);
|
static inline void at25_sectorerase(struct at25_dev_s *priv,
|
||||||
|
off_t offset);
|
||||||
static inline int at25_bulkerase(struct at25_dev_s *priv);
|
static inline int at25_bulkerase(struct at25_dev_s *priv);
|
||||||
static inline void at25_pagewrite(struct at25_dev_s *priv, FAR const uint8_t *buffer,
|
static inline void at25_pagewrite(struct at25_dev_s *priv,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
off_t offset);
|
off_t offset);
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int at25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
static int at25_erase(FAR struct mtd_dev_s *dev,
|
||||||
static ssize_t at25_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf);
|
size_t nblocks);
|
||||||
static ssize_t at25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t at25_bread(FAR struct mtd_dev_s *dev,
|
||||||
size_t nblocks, FAR const uint8_t *buf);
|
off_t startblock,
|
||||||
static ssize_t at25_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
size_t nblocks,
|
||||||
|
FAR uint8_t *buf);
|
||||||
|
static ssize_t at25_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
|
FAR const uint8_t *buf);
|
||||||
|
static ssize_t at25_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
static int at25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int at25_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_lock
|
* Name: at25_lock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void at25_lock(FAR struct spi_dev_s *dev)
|
static void at25_lock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -189,16 +201,18 @@ static void at25_lock(FAR struct spi_dev_s *dev)
|
|||||||
* lock SPI to have exclusive access to the buses for a sequence of
|
* lock SPI to have exclusive access to the buses for a sequence of
|
||||||
* transfers. The bus should be locked before the chip is selected.
|
* transfers. The bus should be locked before the chip is selected.
|
||||||
*
|
*
|
||||||
* This is a blocking call and will not return until we have exclusive access to
|
* This is a blocking call and will not return until we have exclusive
|
||||||
* the SPI bus. We will retain that exclusive access until the bus is unlocked.
|
* access to the SPI bus.
|
||||||
|
* We will retain that exclusive access until the bus is unlocked.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPI_LOCK(dev, true);
|
SPI_LOCK(dev, true);
|
||||||
|
|
||||||
/* After locking the SPI bus, the we also need call the setfrequency, setbits, and
|
/* After locking the SPI bus, the we also need call the setfrequency,
|
||||||
* setmode methods to make sure that the SPI is properly configured for the device.
|
* setbits, and setmode methods to make sure that the SPI is properly
|
||||||
* If the SPI bus is being shared, then it may have been left in an incompatible
|
* configured for the device.
|
||||||
* state.
|
* If the SPI bus is being shared, then it may have been left in an
|
||||||
|
* incompatible state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPI_SETMODE(dev, CONFIG_AT25_SPIMODE);
|
SPI_SETMODE(dev, CONFIG_AT25_SPIMODE);
|
||||||
@@ -207,18 +221,18 @@ static void at25_lock(FAR struct spi_dev_s *dev)
|
|||||||
SPI_SETFREQUENCY(dev, CONFIG_AT25_SPIFREQUENCY);
|
SPI_SETFREQUENCY(dev, CONFIG_AT25_SPIFREQUENCY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_unlock
|
* Name: at25_unlock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void at25_unlock(FAR struct spi_dev_s *dev)
|
static inline void at25_unlock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
SPI_LOCK(dev, false);
|
SPI_LOCK(dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_readid
|
* Name: at25_readid
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int at25_readid(struct at25_dev_s *priv)
|
static inline int at25_readid(struct at25_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -248,7 +262,8 @@ static inline int at25_readid(struct at25_dev_s *priv)
|
|||||||
|
|
||||||
/* Check for a valid manufacturer and memory type */
|
/* Check for a valid manufacturer and memory type */
|
||||||
|
|
||||||
if (manufacturer == AT25_MANUFACTURER && memory == AT25_AT25DF081A_TYPE)
|
if (manufacturer == AT25_MANUFACTURER &&
|
||||||
|
memory == AT25_AT25DF081A_TYPE)
|
||||||
{
|
{
|
||||||
priv->sectorshift = AT25_AT25DF081A_SECTOR_SHIFT;
|
priv->sectorshift = AT25_AT25DF081A_SECTOR_SHIFT;
|
||||||
priv->nsectors = AT25_AT25DF081A_NSECTORS;
|
priv->nsectors = AT25_AT25DF081A_NSECTORS;
|
||||||
@@ -256,7 +271,8 @@ static inline int at25_readid(struct at25_dev_s *priv)
|
|||||||
priv->npages = AT25_AT25DF081A_NPAGES;
|
priv->npages = AT25_AT25DF081A_NPAGES;
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
else if (manufacturer == AT25_MANUFACTURER && memory == AT25_AT25DF321_TYPE)
|
else if (manufacturer == AT25_MANUFACTURER &&
|
||||||
|
memory == AT25_AT25DF321_TYPE)
|
||||||
{
|
{
|
||||||
priv->sectorshift = AT25_AT25DF321_SECTOR_SHIFT;
|
priv->sectorshift = AT25_AT25DF321_SECTOR_SHIFT;
|
||||||
priv->nsectors = AT25_AT25DF321_NSECTORS;
|
priv->nsectors = AT25_AT25DF321_NSECTORS;
|
||||||
@@ -268,9 +284,9 @@ static inline int at25_readid(struct at25_dev_s *priv)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_waitwritecomplete
|
* Name: at25_waitwritecomplete
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void at25_waitwritecomplete(struct at25_dev_s *priv)
|
static void at25_waitwritecomplete(struct at25_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -288,7 +304,9 @@ static void at25_waitwritecomplete(struct at25_dev_s *priv)
|
|||||||
|
|
||||||
SPI_SEND(priv->dev, AT25_RDSR);
|
SPI_SEND(priv->dev, AT25_RDSR);
|
||||||
|
|
||||||
/* Send a dummy byte to generate the clock needed to shift out the status */
|
/* Send a dummy byte to generate the clock needed to shift out
|
||||||
|
* the status
|
||||||
|
*/
|
||||||
|
|
||||||
status = SPI_SEND(priv->dev, AT25_DUMMY);
|
status = SPI_SEND(priv->dev, AT25_DUMMY);
|
||||||
|
|
||||||
@@ -296,9 +314,10 @@ static void at25_waitwritecomplete(struct at25_dev_s *priv)
|
|||||||
|
|
||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
||||||
|
|
||||||
/* Given that writing could take up to few tens of milliseconds, and erasing
|
/* Given that writing could take up to few tens of milliseconds,
|
||||||
* could take more. The following short delay in the "busy" case will allow
|
* and erasing could take more.
|
||||||
* other peripherals to access the SPI bus.
|
* The following short delay in the "busy" case will allow other
|
||||||
|
* peripherals to access the SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((status & AT25_SR_BUSY) != 0)
|
if ((status & AT25_SR_BUSY) != 0)
|
||||||
@@ -318,9 +337,9 @@ static void at25_waitwritecomplete(struct at25_dev_s *priv)
|
|||||||
finfo("Complete, status: 0x%02x\n", status);
|
finfo("Complete, status: 0x%02x\n", status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_writeenable
|
* Name: at25_writeenable
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void at25_writeenable(struct at25_dev_s *priv)
|
static void at25_writeenable(struct at25_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -330,9 +349,9 @@ static void at25_writeenable(struct at25_dev_s *priv)
|
|||||||
finfo("Enabled\n");
|
finfo("Enabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_sectorerase
|
* Name: at25_sectorerase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void at25_sectorerase(struct at25_dev_s *priv, off_t sector)
|
static inline void at25_sectorerase(struct at25_dev_s *priv, off_t sector)
|
||||||
{
|
{
|
||||||
@@ -375,9 +394,9 @@ static inline void at25_sectorerase(struct at25_dev_s *priv, off_t sector)
|
|||||||
finfo("Erased\n");
|
finfo("Erased\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_bulkerase
|
* Name: at25_bulkerase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int at25_bulkerase(struct at25_dev_s *priv)
|
static inline int at25_bulkerase(struct at25_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -410,11 +429,12 @@ static inline int at25_bulkerase(struct at25_dev_s *priv)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_pagewrite
|
* Name: at25_pagewrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void at25_pagewrite(struct at25_dev_s *priv, FAR const uint8_t *buffer,
|
static inline void at25_pagewrite(struct at25_dev_s *priv,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
off_t page)
|
off_t page)
|
||||||
{
|
{
|
||||||
off_t offset = page << 8;
|
off_t offset = page << 8;
|
||||||
@@ -457,11 +477,13 @@ static inline void at25_pagewrite(struct at25_dev_s *priv, FAR const uint8_t *bu
|
|||||||
finfo("Written\n");
|
finfo("Written\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_erase
|
* Name: at25_erase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int at25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
static int at25_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct at25_dev_s *priv = (FAR struct at25_dev_s *)dev;
|
FAR struct at25_dev_s *priv = (FAR struct at25_dev_s *)dev;
|
||||||
size_t blocksleft = nblocks;
|
size_t blocksleft = nblocks;
|
||||||
@@ -483,9 +505,9 @@ static int at25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblock
|
|||||||
return (int)nblocks;
|
return (int)nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_bread
|
* Name: at25_bread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t at25_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t at25_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks,
|
size_t nblocks,
|
||||||
@@ -496,7 +518,9 @@ static ssize_t at25_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
|
|
||||||
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||||
|
|
||||||
/* On this device, we can handle the block read just like the byte-oriented read */
|
/* On this device, we can handle the block read just like the byte-oriented
|
||||||
|
* read
|
||||||
|
*/
|
||||||
|
|
||||||
nbytes = at25_read(dev, startblock << priv->pageshift,
|
nbytes = at25_read(dev, startblock << priv->pageshift,
|
||||||
nblocks << priv->pageshift, buffer);
|
nblocks << priv->pageshift, buffer);
|
||||||
@@ -508,9 +532,9 @@ static ssize_t at25_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
return (int)nbytes;
|
return (int)nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_bwrite
|
* Name: at25_bwrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t at25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t at25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR const uint8_t *buffer)
|
size_t nblocks, FAR const uint8_t *buffer)
|
||||||
@@ -535,11 +559,13 @@ static ssize_t at25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
return nblocks;
|
return nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_read
|
* Name: at25_read
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t at25_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t at25_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct at25_dev_s *priv = (FAR struct at25_dev_s *)dev;
|
FAR struct at25_dev_s *priv = (FAR struct at25_dev_s *)dev;
|
||||||
@@ -587,9 +613,9 @@ static ssize_t at25_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_ioctl
|
* Name: at25_ioctl
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int at25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int at25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@@ -607,13 +633,15 @@ static int at25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
if (geo != NULL)
|
if (geo != NULL)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an array
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* of fixed size blocks.
|
||||||
* appear so.
|
* That is most likely not true, but the client will expect the
|
||||||
|
* device logic to do whatever is necessary to make it appear
|
||||||
|
* so.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = (1 << priv->pageshift);
|
geo->blocksize = (1 << priv->pageshift);
|
||||||
@@ -648,11 +676,11 @@ static int at25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: at25_initialize
|
* Name: at25_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
@@ -660,7 +688,7 @@ static int at25_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
* in the file system, but are created as instances that can be bound to
|
* in the file system, but are created as instances that can be bound to
|
||||||
* other functions (such as a block or character driver front end).
|
* other functions (such as a block or character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *at25_initialize(FAR struct spi_dev_s *dev)
|
FAR struct mtd_dev_s *at25_initialize(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -672,8 +700,8 @@ FAR struct mtd_dev_s *at25_initialize(FAR struct spi_dev_s *dev)
|
|||||||
/* Allocate a state structure (we allocate the structure instead of using
|
/* Allocate a state structure (we allocate the structure instead of using
|
||||||
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
||||||
* The current implementation would handle only one FLASH part per SPI
|
* The current implementation would handle only one FLASH part per SPI
|
||||||
* device (only because of the SPIDEV_FLASH(0) definition) and so would have
|
* device (only because of the SPIDEV_FLASH(0) definition) and so would
|
||||||
* to be extended to handle multiple FLASH parts on the same SPI bus.
|
* have to be extended to handle multiple FLASH parts on the same SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv = (FAR struct at25_dev_s *)kmm_zalloc(sizeof(struct at25_dev_s));
|
priv = (FAR struct at25_dev_s *)kmm_zalloc(sizeof(struct at25_dev_s));
|
||||||
@@ -700,7 +728,9 @@ FAR struct mtd_dev_s *at25_initialize(FAR struct spi_dev_s *dev)
|
|||||||
ret = at25_readid(priv);
|
ret = at25_readid(priv);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
/* Unrecognized! Discard all of that work we just did and return NULL */
|
/* Unrecognized!
|
||||||
|
* Discard all of that work we just did and return NULL
|
||||||
|
*/
|
||||||
|
|
||||||
ferr("ERROR: Unrecognized\n");
|
ferr("ERROR: Unrecognized\n");
|
||||||
kmm_free(priv);
|
kmm_free(priv);
|
||||||
|
|||||||
+183
-142
File diff suppressed because it is too large
Load Diff
+146
-99
@@ -1,4 +1,4 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/gd5f.c
|
* drivers/mtd/gd5f.c
|
||||||
* Driver for GigaDevice SPI nand flash.
|
* Driver for GigaDevice SPI nand flash.
|
||||||
*
|
*
|
||||||
@@ -32,11 +32,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
@@ -54,11 +54,11 @@
|
|||||||
#include <nuttx/spi/spi.h>
|
#include <nuttx/spi/spi.h>
|
||||||
#include <nuttx/mtd/mtd.h>
|
#include <nuttx/mtd/mtd.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Configuration ********************************************************************/
|
/* Configuration ************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_GD5F_SPIMODE
|
#ifndef CONFIG_GD5F_SPIMODE
|
||||||
# define CONFIG_GD5F_SPIMODE SPIDEV_MODE0
|
# define CONFIG_GD5F_SPIMODE SPIDEV_MODE0
|
||||||
@@ -68,9 +68,10 @@
|
|||||||
# define CONFIG_GD5F_SPIFREQUENCY 20000000
|
# define CONFIG_GD5F_SPIFREQUENCY 20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* GD5F Instructions ****************************************************************/
|
/* GD5F Instructions ********************************************************/
|
||||||
|
|
||||||
/* Command Value Description Addr Data */
|
/* Command Value Description Addr Data */
|
||||||
|
|
||||||
/* Dummy */
|
/* Dummy */
|
||||||
|
|
||||||
#define GD5F_GET_FEATURE 0x0f /* Get features 1 0 1 */
|
#define GD5F_GET_FEATURE 0x0f /* Get features 1 0 1 */
|
||||||
@@ -91,10 +92,9 @@
|
|||||||
#define GD5F_WRITE_ENABLE 0x06 /* 0 0 0 */
|
#define GD5F_WRITE_ENABLE 0x06 /* 0 0 0 */
|
||||||
#define GD5F_WRITE_DISABLE 0x04 /* 0 0 0 */
|
#define GD5F_WRITE_DISABLE 0x04 /* 0 0 0 */
|
||||||
#define GD5F_RESET 0xff /* Reset the device 0 0 0 */
|
#define GD5F_RESET 0xff /* Reset the device 0 0 0 */
|
||||||
|
|
||||||
#define GD5F_DUMMY 0x00 /* No Operation 0 0 0 */
|
#define GD5F_DUMMY 0x00 /* No Operation 0 0 0 */
|
||||||
|
|
||||||
/* Feature register *****************************************************************/
|
/* Feature register *********************************************************/
|
||||||
|
|
||||||
/* JEDEC Read ID register values */
|
/* JEDEC Read ID register values */
|
||||||
|
|
||||||
@@ -153,9 +153,9 @@
|
|||||||
#define GD5F_FEATURE_ECC_OFFSET 4
|
#define GD5F_FEATURE_ECC_OFFSET 4
|
||||||
#define GD5F_ECC_STATUS_MASK 0x0f
|
#define GD5F_ECC_STATUS_MASK 0x0f
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
||||||
* must appear at the beginning of the definition so that you can freely
|
* must appear at the beginning of the definition so that you can freely
|
||||||
@@ -173,9 +173,9 @@ struct gd5f_dev_s
|
|||||||
uint8_t eccstatus; /* Internal ECC status */
|
uint8_t eccstatus; /* Internal ECC status */
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
|
|
||||||
@@ -183,18 +183,26 @@ static inline void gd5f_lock(FAR struct spi_dev_s *dev);
|
|||||||
static inline void gd5f_unlock(FAR struct spi_dev_s *dev);
|
static inline void gd5f_unlock(FAR struct spi_dev_s *dev);
|
||||||
|
|
||||||
static int gd5f_readid(FAR struct gd5f_dev_s *priv);
|
static int gd5f_readid(FAR struct gd5f_dev_s *priv);
|
||||||
static bool gd5f_waitstatus(FAR struct gd5f_dev_s *priv, uint8_t mask,
|
static bool gd5f_waitstatus(FAR struct gd5f_dev_s *priv,
|
||||||
|
uint8_t mask,
|
||||||
bool successif);
|
bool successif);
|
||||||
static inline void gd5f_writeenable(FAR struct gd5f_dev_s *priv);
|
static inline void gd5f_writeenable(FAR struct gd5f_dev_s *priv);
|
||||||
static inline void gd5f_writedisable(FAR struct gd5f_dev_s *priv);
|
static inline void gd5f_writedisable(FAR struct gd5f_dev_s *priv);
|
||||||
static bool gd5f_sectorerase(FAR struct gd5f_dev_s *priv, off_t startsector);
|
static bool gd5f_sectorerase(FAR struct gd5f_dev_s *priv,
|
||||||
static void gd5f_readbuffer(FAR struct gd5f_dev_s *priv, uint32_t address,
|
off_t startsector);
|
||||||
uint8_t *buffer, size_t length);
|
static void gd5f_readbuffer(FAR struct gd5f_dev_s *priv,
|
||||||
static bool gd5f_read_page(FAR struct gd5f_dev_s *priv, uint32_t position);
|
uint32_t address,
|
||||||
|
uint8_t *buffer,
|
||||||
|
size_t length);
|
||||||
|
static bool gd5f_read_page(FAR struct gd5f_dev_s *priv,
|
||||||
|
uint32_t position);
|
||||||
|
|
||||||
static void gd5f_write_to_cache(FAR struct gd5f_dev_s *priv, uint32_t address,
|
static void gd5f_write_to_cache(FAR struct gd5f_dev_s *priv,
|
||||||
const uint8_t *buffer, size_t length);
|
uint32_t address,
|
||||||
static bool gd5f_execute_write(FAR struct gd5f_dev_s *priv, uint32_t position);
|
const uint8_t *buffer,
|
||||||
|
size_t length);
|
||||||
|
static bool gd5f_execute_write(FAR struct gd5f_dev_s *priv,
|
||||||
|
uint32_t position);
|
||||||
|
|
||||||
static inline void gd5f_eccstatusread(FAR struct gd5f_dev_s *priv);
|
static inline void gd5f_eccstatusread(FAR struct gd5f_dev_s *priv);
|
||||||
static inline void gd5f_enable_ecc(FAR struct gd5f_dev_s *priv);
|
static inline void gd5f_enable_ecc(FAR struct gd5f_dev_s *priv);
|
||||||
@@ -202,24 +210,36 @@ static inline void gd5f_unlockblocks(FAR struct gd5f_dev_s *priv);
|
|||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static ssize_t gd5f_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t gd5f_bread(FAR struct mtd_dev_s *dev,
|
||||||
size_t nblocks, FAR uint8_t *buffer);
|
off_t startblock,
|
||||||
static ssize_t gd5f_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
size_t nblocks,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
static ssize_t gd5f_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t gd5f_read(FAR struct mtd_dev_s *dev,
|
||||||
size_t nblocks, FAR const uint8_t *buffer);
|
off_t offset,
|
||||||
static ssize_t gd5f_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
size_t nbytes,
|
||||||
|
FAR uint8_t *buffer);
|
||||||
|
static ssize_t gd5f_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
FAR const uint8_t *buffer);
|
FAR const uint8_t *buffer);
|
||||||
static int gd5f_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static ssize_t gd5f_write(FAR struct mtd_dev_s *dev,
|
||||||
static int gd5f_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
|
FAR const uint8_t *buffer);
|
||||||
|
static int gd5f_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
static int gd5f_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks);
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_lock
|
* Name: gd5f_lock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void gd5f_lock(FAR struct spi_dev_s *dev)
|
static inline void gd5f_lock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -231,18 +251,18 @@ static inline void gd5f_lock(FAR struct spi_dev_s *dev)
|
|||||||
SPI_SETFREQUENCY(dev, CONFIG_GD5F_SPIFREQUENCY);
|
SPI_SETFREQUENCY(dev, CONFIG_GD5F_SPIFREQUENCY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_unlock
|
* Name: gd5f_unlock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void gd5f_unlock(FAR struct spi_dev_s *dev)
|
static inline void gd5f_unlock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
SPI_LOCK(dev, false);
|
SPI_LOCK(dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_readid
|
* Name: gd5f_readid
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int gd5f_readid(FAR struct gd5f_dev_s *priv)
|
static int gd5f_readid(FAR struct gd5f_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -303,11 +323,13 @@ static int gd5f_readid(FAR struct gd5f_dev_s *priv)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_waitstatus
|
* Name: gd5f_waitstatus
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static bool gd5f_waitstatus(FAR struct gd5f_dev_s *priv, uint8_t mask, bool successif)
|
static bool gd5f_waitstatus(FAR struct gd5f_dev_s *priv,
|
||||||
|
uint8_t mask,
|
||||||
|
bool successif)
|
||||||
{
|
{
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
|
||||||
@@ -337,9 +359,9 @@ static bool gd5f_waitstatus(FAR struct gd5f_dev_s *priv, uint8_t mask, bool succ
|
|||||||
return successif ? ((status & mask) != 0) : ((status & mask) == 0);
|
return successif ? ((status & mask) != 0) : ((status & mask) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_writeenable
|
* Name: gd5f_writeenable
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void gd5f_writeenable(FAR struct gd5f_dev_s *priv)
|
static inline void gd5f_writeenable(FAR struct gd5f_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -356,9 +378,9 @@ static inline void gd5f_writeenable(FAR struct gd5f_dev_s *priv)
|
|||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_writedisable
|
* Name: gd5f_writedisable
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void gd5f_writedisable(FAR struct gd5f_dev_s *priv)
|
static inline void gd5f_writedisable(FAR struct gd5f_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -375,13 +397,15 @@ static inline void gd5f_writedisable(FAR struct gd5f_dev_s *priv)
|
|||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_sectorerase (128K)
|
* Name: gd5f_sectorerase (128K)
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static bool gd5f_sectorerase(FAR struct gd5f_dev_s *priv, off_t startsector)
|
static bool gd5f_sectorerase(FAR struct gd5f_dev_s *priv,
|
||||||
|
off_t startsector)
|
||||||
{
|
{
|
||||||
const uint32_t block = startsector << (priv->sectorshift - priv->pageshift);
|
const uint32_t block = startsector << (priv->sectorshift -
|
||||||
|
priv->pageshift);
|
||||||
|
|
||||||
finfo("block sector: %08lx\n", (long)block);
|
finfo("block sector: %08lx\n", (long)block);
|
||||||
|
|
||||||
@@ -408,16 +432,20 @@ static bool gd5f_sectorerase(FAR struct gd5f_dev_s *priv, off_t startsector)
|
|||||||
return gd5f_waitstatus(priv, GD5F_SR_E_FAIL, false);
|
return gd5f_waitstatus(priv, GD5F_SR_E_FAIL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_erase
|
* Name: gd5f_erase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int gd5f_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
static int gd5f_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct gd5f_dev_s *priv = (FAR struct gd5f_dev_s *)dev;
|
FAR struct gd5f_dev_s *priv = (FAR struct gd5f_dev_s *)dev;
|
||||||
size_t blocksleft = nblocks;
|
size_t blocksleft = nblocks;
|
||||||
|
|
||||||
finfo("Erase: startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
finfo("Erase: startblock: %08lx nblocks: %d\n",
|
||||||
|
(long)startblock,
|
||||||
|
(int)nblocks);
|
||||||
|
|
||||||
/* Lock access to the SPI bus until we complete the erase */
|
/* Lock access to the SPI bus until we complete the erase */
|
||||||
|
|
||||||
@@ -442,12 +470,14 @@ static int gd5f_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblock
|
|||||||
return nblocks - blocksleft;
|
return nblocks - blocksleft;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_readbuffer
|
* Name: gd5f_readbuffer
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void gd5f_readbuffer(FAR struct gd5f_dev_s *priv, uint32_t address,
|
static void gd5f_readbuffer(FAR struct gd5f_dev_s *priv,
|
||||||
uint8_t *buffer, size_t length)
|
uint32_t address,
|
||||||
|
uint8_t *buffer,
|
||||||
|
size_t length)
|
||||||
{
|
{
|
||||||
const uint16_t offset = address & ((1 << priv->pageshift) - 1);
|
const uint16_t offset = address & ((1 << priv->pageshift) - 1);
|
||||||
|
|
||||||
@@ -475,9 +505,9 @@ static void gd5f_readbuffer(FAR struct gd5f_dev_s *priv, uint32_t address,
|
|||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_read_page
|
* Name: gd5f_read_page
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static bool gd5f_read_page(FAR struct gd5f_dev_s *priv, uint32_t pageaddress)
|
static bool gd5f_read_page(FAR struct gd5f_dev_s *priv, uint32_t pageaddress)
|
||||||
{
|
{
|
||||||
@@ -515,11 +545,13 @@ static bool gd5f_read_page(FAR struct gd5f_dev_s *priv, uint32_t pageaddress)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_read
|
* Name: gd5f_read
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t gd5f_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t gd5f_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct gd5f_dev_s *priv = (FAR struct gd5f_dev_s *)dev;
|
FAR struct gd5f_dev_s *priv = (FAR struct gd5f_dev_s *)dev;
|
||||||
@@ -538,9 +570,12 @@ static ssize_t gd5f_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
|
|
||||||
while (bytesleft)
|
while (bytesleft)
|
||||||
{
|
{
|
||||||
const uint32_t pageaddress = (position >> priv->pageshift) << priv->pageshift;
|
const uint32_t pageaddress =
|
||||||
const uint32_t spaceleft = pageaddress + (1 << priv->pageshift) - position;
|
(position >> priv->pageshift) << priv->pageshift;
|
||||||
const size_t chunklength = bytesleft < spaceleft ? bytesleft : spaceleft;
|
const uint32_t spaceleft =
|
||||||
|
pageaddress + (1 << priv->pageshift) - position;
|
||||||
|
const size_t chunklength =
|
||||||
|
bytesleft < spaceleft ? bytesleft : spaceleft;
|
||||||
|
|
||||||
if (!gd5f_read_page(priv, pageaddress))
|
if (!gd5f_read_page(priv, pageaddress))
|
||||||
{
|
{
|
||||||
@@ -560,9 +595,9 @@ static ssize_t gd5f_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
return nbytes - bytesleft;
|
return nbytes - bytesleft;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_bread
|
* Name: gd5f_bread
|
||||||
**************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t gd5f_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t gd5f_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buffer)
|
size_t nblocks, FAR uint8_t *buffer)
|
||||||
@@ -583,12 +618,14 @@ static ssize_t gd5f_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_write_to_cache
|
* Name: gd5f_write_to_cache
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void gd5f_write_to_cache(FAR struct gd5f_dev_s *priv, uint32_t address,
|
static void gd5f_write_to_cache(FAR struct gd5f_dev_s *priv,
|
||||||
const uint8_t *buffer, size_t length)
|
uint32_t address,
|
||||||
|
const uint8_t *buffer,
|
||||||
|
size_t length)
|
||||||
{
|
{
|
||||||
const uint16_t offset = address & ((1 << priv->pageshift) - 1);
|
const uint16_t offset = address & ((1 << priv->pageshift) - 1);
|
||||||
|
|
||||||
@@ -614,11 +651,12 @@ static void gd5f_write_to_cache(FAR struct gd5f_dev_s *priv, uint32_t address,
|
|||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_execute_write
|
* Name: gd5f_execute_write
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static bool gd5f_execute_write(FAR struct gd5f_dev_s *priv, uint32_t pageaddress)
|
static bool gd5f_execute_write(FAR struct gd5f_dev_s *priv,
|
||||||
|
uint32_t pageaddress)
|
||||||
{
|
{
|
||||||
const uint32_t row = pageaddress >> priv->pageshift;
|
const uint32_t row = pageaddress >> priv->pageshift;
|
||||||
|
|
||||||
@@ -640,11 +678,13 @@ static bool gd5f_execute_write(FAR struct gd5f_dev_s *priv, uint32_t pageaddress
|
|||||||
return gd5f_waitstatus(priv, GD5F_SR_P_FAIL, false);
|
return gd5f_waitstatus(priv, GD5F_SR_P_FAIL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_write
|
* Name: gd5f_write
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t gd5f_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t gd5f_write(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR const uint8_t *buffer)
|
FAR const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct gd5f_dev_s *priv = (FAR struct gd5f_dev_s *)dev;
|
FAR struct gd5f_dev_s *priv = (FAR struct gd5f_dev_s *)dev;
|
||||||
@@ -660,9 +700,12 @@ static ssize_t gd5f_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes
|
|||||||
|
|
||||||
while (bytesleft)
|
while (bytesleft)
|
||||||
{
|
{
|
||||||
const uint32_t pageaddress = (position >> priv->pageshift) << priv->pageshift;
|
const uint32_t pageaddress =
|
||||||
const uint32_t spaceleft = pageaddress + (1 << priv->pageshift) - position;
|
(position >> priv->pageshift) << priv->pageshift;
|
||||||
const size_t chunklength = bytesleft < spaceleft ? bytesleft : spaceleft;
|
const uint32_t spaceleft =
|
||||||
|
pageaddress + (1 << priv->pageshift) - position;
|
||||||
|
const size_t chunklength =
|
||||||
|
bytesleft < spaceleft ? bytesleft : spaceleft;
|
||||||
|
|
||||||
gd5f_write_to_cache(priv, position, buffer, chunklength);
|
gd5f_write_to_cache(priv, position, buffer, chunklength);
|
||||||
gd5f_writeenable(priv);
|
gd5f_writeenable(priv);
|
||||||
@@ -681,9 +724,9 @@ static ssize_t gd5f_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes
|
|||||||
return nbytes - bytesleft;
|
return nbytes - bytesleft;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_bwrite
|
* Name: gd5f_bwrite
|
||||||
**************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t gd5f_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t gd5f_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR const uint8_t *buffer)
|
size_t nblocks, FAR const uint8_t *buffer)
|
||||||
@@ -707,9 +750,9 @@ static ssize_t gd5f_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mx25l_ioctl
|
* Name: mx25l_ioctl
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int gd5f_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int gd5f_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@@ -750,7 +793,8 @@ static int gd5f_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
{
|
{
|
||||||
uint8_t *result = (uint8_t *)arg;
|
uint8_t *result = (uint8_t *)arg;
|
||||||
*result =
|
*result =
|
||||||
(priv->eccstatus & GD5F_FEATURE_ECC_MASK) >> GD5F_FEATURE_ECC_OFFSET;
|
(priv->eccstatus & GD5F_FEATURE_ECC_MASK)
|
||||||
|
>> GD5F_FEATURE_ECC_OFFSET;
|
||||||
|
|
||||||
ret = OK;
|
ret = OK;
|
||||||
}
|
}
|
||||||
@@ -765,9 +809,9 @@ static int gd5f_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_eccstatusread
|
* Name: gd5f_eccstatusread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void gd5f_eccstatusread(FAR struct gd5f_dev_s *priv)
|
static inline void gd5f_eccstatusread(FAR struct gd5f_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -778,9 +822,9 @@ static inline void gd5f_eccstatusread(FAR struct gd5f_dev_s *priv)
|
|||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(priv->spi_devid), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_enable_ecc
|
* Name: gd5f_enable_ecc
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void gd5f_enable_ecc(FAR struct gd5f_dev_s *priv)
|
static inline void gd5f_enable_ecc(FAR struct gd5f_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -799,9 +843,9 @@ static inline void gd5f_enable_ecc(FAR struct gd5f_dev_s *priv)
|
|||||||
gd5f_unlock(priv->dev);
|
gd5f_unlock(priv->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_unlockblocks
|
* Name: gd5f_unlockblocks
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void gd5f_unlockblocks(FAR struct gd5f_dev_s *priv)
|
static inline void gd5f_unlockblocks(FAR struct gd5f_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -820,19 +864,20 @@ static inline void gd5f_unlockblocks(FAR struct gd5f_dev_s *priv)
|
|||||||
gd5f_unlock(priv->dev);
|
gd5f_unlock(priv->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: gd5f_initialize
|
* Name: gd5f_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Create an initialize MTD device instance. MTD devices are not registered
|
* Create an initialize MTD device instance.
|
||||||
* in the file system, but are created as instances that can be bound to
|
* MTD devices are not registered in the file system, but are created
|
||||||
* other functions (such as a block or character driver front end).
|
* as instances that can be bound to other functions(such as a block
|
||||||
|
* or character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *gd5f_initialize(FAR struct spi_dev_s *dev,
|
FAR struct mtd_dev_s *gd5f_initialize(FAR struct spi_dev_s *dev,
|
||||||
uint32_t spi_devid)
|
uint32_t spi_devid)
|
||||||
@@ -876,7 +921,9 @@ FAR struct mtd_dev_s *gd5f_initialize(FAR struct spi_dev_s *dev,
|
|||||||
ret = gd5f_readid(priv);
|
ret = gd5f_readid(priv);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
/* Unrecognized! Discard all of that work we just did and return NULL */
|
/* Unrecognized! Discard all of that work we just did and
|
||||||
|
* return NULL
|
||||||
|
*/
|
||||||
|
|
||||||
ferr("ERROR: Unrecognized\n");
|
ferr("ERROR: Unrecognized\n");
|
||||||
kmm_free(priv);
|
kmm_free(priv);
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ static unsigned int hamming_bitsinbyte(uint8_t byte)
|
|||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte >>= 1;
|
byte >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +195,8 @@ static void hamming_compute256(FAR const uint8_t *data, FAR uint8_t *code)
|
|||||||
colsum >>= 1;
|
colsum >>= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now, we must interleave the parity values, to obtain the following layout:
|
/* Now, we must interleave the parity values,
|
||||||
|
* to obtain the following layout:
|
||||||
* Code[0] = Line1
|
* Code[0] = Line1
|
||||||
* Code[1] = Line2
|
* Code[1] = Line2
|
||||||
* Code[2] = Column
|
* Code[2] = Column
|
||||||
@@ -415,7 +417,9 @@ void hamming_compute256x(FAR const uint8_t *data, size_t size, uint8_t *code)
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
int hamming_verify256x(FAR uint8_t *data, size_t size, FAR const uint8_t *code)
|
int hamming_verify256x(FAR uint8_t *data,
|
||||||
|
size_t size,
|
||||||
|
FAR const uint8_t *code)
|
||||||
{
|
{
|
||||||
ssize_t remaining = (ssize_t)size;
|
ssize_t remaining = (ssize_t)size;
|
||||||
int result = HAMMING_SUCCESS;
|
int result = HAMMING_SUCCESS;
|
||||||
|
|||||||
+143
-94
@@ -1,4 +1,4 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/is25xp.c
|
* drivers/mtd/is25xp.c
|
||||||
* Driver for SPI-based IS25LPxx parts 32MBit and larger.
|
* Driver for SPI-based IS25LPxx parts 32MBit and larger.
|
||||||
*
|
*
|
||||||
@@ -37,11 +37,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
@@ -59,15 +59,16 @@
|
|||||||
#include <nuttx/spi/spi.h>
|
#include <nuttx/spi/spi.h>
|
||||||
#include <nuttx/mtd/mtd.h>
|
#include <nuttx/mtd/mtd.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Configuration ********************************************************************/
|
/* Configuration ************************************************************/
|
||||||
/* Per the data sheet, IS25xP parts can be driven with either SPI mode 0 (CPOL=0 and
|
|
||||||
* CPHA=0) or mode 3 (CPOL=1 and CPHA=1). So you may need to specify
|
/* Per the data sheet, IS25xP parts can be driven with either SPI mode 0
|
||||||
* CONFIG_IS25XP_SPIMODE to select the best mode for your device. If
|
* (CPOL=0 and CPHA=0) or mode 3 (CPOL=1 and CPHA=1). So you may need to
|
||||||
* CONFIG_IS25XP_SPIMODE is not defined, mode 0 will be used.
|
* specify CONFIG_IS25XP_SPIMODE to select the best mode for your device.
|
||||||
|
* If CONFIG_IS25XP_SPIMODE is not defined, mode 0 will be used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_IS25XP_SPIMODE
|
#ifndef CONFIG_IS25XP_SPIMODE
|
||||||
@@ -80,7 +81,8 @@
|
|||||||
#define CONFIG_IS25XP_SPIFREQUENCY 20000000
|
#define CONFIG_IS25XP_SPIFREQUENCY 20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* IS25 Registers *******************************************************************/
|
/* IS25 Registers ***********************************************************/
|
||||||
|
|
||||||
/* Identification register values */
|
/* Identification register values */
|
||||||
|
|
||||||
#define IS25_MANUFACTURER 0x9d
|
#define IS25_MANUFACTURER 0x9d
|
||||||
@@ -108,14 +110,16 @@
|
|||||||
#define IS25_IS25LP128_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */
|
#define IS25_IS25LP128_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */
|
||||||
#define IS25_IS25LP128_NPAGES 65536
|
#define IS25_IS25LP128_NPAGES 65536
|
||||||
|
|
||||||
|
|
||||||
/* Instructions */
|
/* Instructions */
|
||||||
|
|
||||||
/* Command Value N Description Addr Dummy Data */
|
/* Command Value N Description Addr Dummy Data */
|
||||||
|
|
||||||
#define IS25_WREN 0x06 /* 1 Write Enable 0 0 0 */
|
#define IS25_WREN 0x06 /* 1 Write Enable 0 0 0 */
|
||||||
#define IS25_WRDI 0x04 /* 1 Write Disable 0 0 0 */
|
#define IS25_WRDI 0x04 /* 1 Write Disable 0 0 0 */
|
||||||
#define IS25_RDID 0x9f /* 1 Read Identification 0 0 1-3 */
|
#define IS25_RDID 0x9f /* 1 Read Identification 0 0 1-3 */
|
||||||
#define IS25_RDSR 0x05 /* 1 Read Status Register 0 0 >=1 */
|
#define IS25_RDSR 0x05 /* 1 Read Status Register 0 0 >=1 */
|
||||||
//#define IS25_EWSR 0x50 /* 1 Write enable status 0 0 0 */
|
|
||||||
|
/* #define IS25_EWSR 0x50 1 Write enable status 0 0 0 */
|
||||||
#define IS25_WRSR 0x01 /* 1 Write Status Register 0 0 1 */
|
#define IS25_WRSR 0x01 /* 1 Write Status Register 0 0 1 */
|
||||||
#define IS25_READ 0x03 /* 1 Read Data Bytes 3 0 >=1 */
|
#define IS25_READ 0x03 /* 1 Read Data Bytes 3 0 >=1 */
|
||||||
#define IS25_FAST_READ 0x0b /* 1 Higher speed read 3 1 >=1 */
|
#define IS25_FAST_READ 0x0b /* 1 Higher speed read 3 1 >=1 */
|
||||||
@@ -151,9 +155,9 @@
|
|||||||
|
|
||||||
#define IS25_DUMMY 0xa5
|
#define IS25_DUMMY 0xa5
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
||||||
* must appear at the beginning of the definition so that you can freely
|
* must appear at the beginning of the definition so that you can freely
|
||||||
@@ -171,9 +175,9 @@ struct is25xp_dev_s
|
|||||||
uint8_t lastwaswrite; /* Indicates if last operation was write */
|
uint8_t lastwaswrite; /* Indicates if last operation was write */
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
|
|
||||||
@@ -182,29 +186,42 @@ static inline void is25xp_unlock(FAR struct spi_dev_s *dev);
|
|||||||
static inline int is25xp_readid(struct is25xp_dev_s *priv);
|
static inline int is25xp_readid(struct is25xp_dev_s *priv);
|
||||||
static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv);
|
static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv);
|
||||||
static void is25xp_writeenable(struct is25xp_dev_s *priv);
|
static void is25xp_writeenable(struct is25xp_dev_s *priv);
|
||||||
static inline void is25xp_sectorerase(struct is25xp_dev_s *priv, off_t offset, uint8_t type);
|
static inline void is25xp_sectorerase(struct is25xp_dev_s *priv,
|
||||||
|
off_t offset,
|
||||||
|
uint8_t type);
|
||||||
static inline int is25xp_bulkerase(struct is25xp_dev_s *priv);
|
static inline int is25xp_bulkerase(struct is25xp_dev_s *priv);
|
||||||
static inline void is25xp_pagewrite(struct is25xp_dev_s *priv, FAR const uint8_t *buffer,
|
static inline void is25xp_pagewrite(struct is25xp_dev_s *priv,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
off_t offset);
|
off_t offset);
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int is25xp_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
static int is25xp_erase(FAR struct mtd_dev_s *dev,
|
||||||
static ssize_t is25xp_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
off_t startblock,
|
||||||
|
size_t nblocks);
|
||||||
|
static ssize_t is25xp_bread(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf);
|
size_t nblocks, FAR uint8_t *buf);
|
||||||
static ssize_t is25xp_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t is25xp_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
size_t nblocks, FAR const uint8_t *buf);
|
size_t nblocks, FAR const uint8_t *buf);
|
||||||
static ssize_t is25xp_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t is25xp_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
static ssize_t is25xp_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t is25xp_write(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR const uint8_t *buffer);
|
FAR const uint8_t *buffer);
|
||||||
#endif
|
#endif
|
||||||
static int is25xp_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int is25xp_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_lock
|
* Name: is25xp_lock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void is25xp_lock(FAR struct spi_dev_s *dev)
|
static void is25xp_lock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -212,16 +229,18 @@ static void is25xp_lock(FAR struct spi_dev_s *dev)
|
|||||||
* lock SPI to have exclusive access to the buses for a sequence of
|
* lock SPI to have exclusive access to the buses for a sequence of
|
||||||
* transfers. The bus should be locked before the chip is selected.
|
* transfers. The bus should be locked before the chip is selected.
|
||||||
*
|
*
|
||||||
* This is a blocking call and will not return until we have exclusive access to
|
* This is a blocking call and will not return until we have exclusive
|
||||||
* the SPI bus. We will retain that exclusive access until the bus is unlocked.
|
* access to the SPI bus. We will retain that exclusive access until the
|
||||||
|
* bus is unlocked.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPI_LOCK(dev, true);
|
SPI_LOCK(dev, true);
|
||||||
|
|
||||||
/* After locking the SPI bus, the we also need call the setfrequency, setbits, and
|
/* After locking the SPI bus, the we also need call the setfrequency,
|
||||||
* setmode methods to make sure that the SPI is properly configured for the device.
|
* setbits, and setmode methods to make sure that the SPI is properly
|
||||||
* If the SPI bus is being shared, then it may have been left in an incompatible
|
* configured for the device.
|
||||||
* state.
|
* If the SPI bus is being shared, then it may have been left in an
|
||||||
|
* incompatible state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPI_SETMODE(dev, CONFIG_IS25XP_SPIMODE);
|
SPI_SETMODE(dev, CONFIG_IS25XP_SPIMODE);
|
||||||
@@ -230,18 +249,18 @@ static void is25xp_lock(FAR struct spi_dev_s *dev)
|
|||||||
SPI_SETFREQUENCY(dev, CONFIG_IS25XP_SPIFREQUENCY);
|
SPI_SETFREQUENCY(dev, CONFIG_IS25XP_SPIFREQUENCY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_unlock
|
* Name: is25xp_unlock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void is25xp_unlock(FAR struct spi_dev_s *dev)
|
static inline void is25xp_unlock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
SPI_LOCK(dev, false);
|
SPI_LOCK(dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_readid
|
* Name: is25xp_readid
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int is25xp_readid(struct is25xp_dev_s *priv)
|
static inline int is25xp_readid(struct is25xp_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -302,9 +321,9 @@ static inline int is25xp_readid(struct is25xp_dev_s *priv)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_waitwritecomplete
|
* Name: is25xp_waitwritecomplete
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv)
|
static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -335,7 +354,9 @@ static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv)
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
/* Send a dummy byte to generate the clock needed to shift out the status */
|
/* Send a dummy byte to generate the clock needed to shift out
|
||||||
|
* the status
|
||||||
|
*/
|
||||||
|
|
||||||
status = SPI_SEND(priv->dev, IS25_DUMMY);
|
status = SPI_SEND(priv->dev, IS25_DUMMY);
|
||||||
}
|
}
|
||||||
@@ -359,7 +380,9 @@ static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv)
|
|||||||
|
|
||||||
SPI_SEND(priv->dev, IS25_RDSR);
|
SPI_SEND(priv->dev, IS25_RDSR);
|
||||||
|
|
||||||
/* Send a dummy byte to generate the clock needed to shift out the status */
|
/* Send a dummy byte to generate the clock needed to shift out
|
||||||
|
* the status
|
||||||
|
*/
|
||||||
|
|
||||||
status = SPI_SEND(priv->dev, IS25_DUMMY);
|
status = SPI_SEND(priv->dev, IS25_DUMMY);
|
||||||
|
|
||||||
@@ -367,9 +390,9 @@ static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv)
|
|||||||
|
|
||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
||||||
|
|
||||||
/* Given that writing could take up to few tens of milliseconds, and erasing
|
/* Given that writing could take up to few tens of milliseconds,
|
||||||
* could take more. The following short delay in the "busy" case will allow
|
* and erasing could take more. The following short delay in the
|
||||||
* other peripherals to access the SPI bus.
|
* "busy" case will allow other peripherals to access the SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((status & IS25_SR_WIP) != 0)
|
if ((status & IS25_SR_WIP) != 0)
|
||||||
@@ -387,9 +410,9 @@ static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv)
|
|||||||
finfo("Complete\n");
|
finfo("Complete\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_writeenable
|
* Name: is25xp_writeenable
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void is25xp_writeenable(struct is25xp_dev_s *priv)
|
static void is25xp_writeenable(struct is25xp_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -407,9 +430,9 @@ static void is25xp_writeenable(struct is25xp_dev_s *priv)
|
|||||||
finfo("Enabled\n");
|
finfo("Enabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_unprotect
|
* Name: is25xp_unprotect
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void is25xp_unprotect(struct is25xp_dev_s *priv)
|
static void is25xp_unprotect(struct is25xp_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -429,11 +452,13 @@ static void is25xp_unprotect(struct is25xp_dev_s *priv)
|
|||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_sectorerase
|
* Name: is25xp_sectorerase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void is25xp_sectorerase(struct is25xp_dev_s *priv, off_t sector, uint8_t type)
|
static void is25xp_sectorerase(struct is25xp_dev_s *priv,
|
||||||
|
off_t sector,
|
||||||
|
uint8_t type)
|
||||||
{
|
{
|
||||||
off_t offset;
|
off_t offset;
|
||||||
|
|
||||||
@@ -479,9 +504,9 @@ static void is25xp_sectorerase(struct is25xp_dev_s *priv, off_t sector, uint8_t
|
|||||||
finfo("Erased\n");
|
finfo("Erased\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_bulkerase
|
* Name: is25xp_bulkerase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int is25xp_bulkerase(struct is25xp_dev_s *priv)
|
static inline int is25xp_bulkerase(struct is25xp_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -516,11 +541,12 @@ static inline int is25xp_bulkerase(struct is25xp_dev_s *priv)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_pagewrite
|
* Name: is25xp_pagewrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void is25xp_pagewrite(struct is25xp_dev_s *priv, FAR const uint8_t *buffer,
|
static inline void is25xp_pagewrite(struct is25xp_dev_s *priv,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
off_t page)
|
off_t page)
|
||||||
{
|
{
|
||||||
off_t offset = page << priv->pageshift;
|
off_t offset = page << priv->pageshift;
|
||||||
@@ -564,9 +590,9 @@ static inline void is25xp_pagewrite(struct is25xp_dev_s *priv, FAR const uint8_t
|
|||||||
finfo("Written\n");
|
finfo("Written\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_bytewrite
|
* Name: is25xp_bytewrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
static inline void is25xp_bytewrite(struct is25xp_dev_s *priv,
|
static inline void is25xp_bytewrite(struct is25xp_dev_s *priv,
|
||||||
@@ -613,11 +639,13 @@ static inline void is25xp_bytewrite(struct is25xp_dev_s *priv,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_erase
|
* Name: is25xp_erase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int is25xp_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
static int is25xp_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
||||||
size_t blocksleft = nblocks;
|
size_t blocksleft = nblocks;
|
||||||
@@ -689,11 +717,13 @@ static int is25xp_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblo
|
|||||||
return (int)nblocks;
|
return (int)nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_bread
|
* Name: is25xp_bread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t is25xp_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
|
static ssize_t is25xp_bread(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
||||||
@@ -701,9 +731,14 @@ static ssize_t is25xp_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t
|
|||||||
|
|
||||||
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||||
|
|
||||||
/* On this device, we can handle the block read just like the byte-oriented read */
|
/* On this device, we can handle the block read just like the byte-oriented
|
||||||
|
* read
|
||||||
|
*/
|
||||||
|
|
||||||
nbytes = is25xp_read(dev, startblock << priv->pageshift, nblocks << priv->pageshift, buffer);
|
nbytes = is25xp_read(dev,
|
||||||
|
startblock << priv->pageshift,
|
||||||
|
nblocks << priv->pageshift,
|
||||||
|
buffer);
|
||||||
if (nbytes > 0)
|
if (nbytes > 0)
|
||||||
{
|
{
|
||||||
return nbytes >> priv->pageshift;
|
return nbytes >> priv->pageshift;
|
||||||
@@ -712,11 +747,13 @@ static ssize_t is25xp_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t
|
|||||||
return (int)nbytes;
|
return (int)nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_bwrite
|
* Name: is25xp_bwrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t is25xp_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
|
static ssize_t is25xp_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
FAR const uint8_t *buffer)
|
FAR const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
||||||
@@ -739,11 +776,13 @@ static ssize_t is25xp_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t
|
|||||||
return nblocks;
|
return nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_read
|
* Name: is25xp_read
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t is25xp_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t is25xp_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
||||||
@@ -794,12 +833,14 @@ static ssize_t is25xp_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbyte
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_write
|
* Name: is25xp_write
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
static ssize_t is25xp_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t is25xp_write(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR const uint8_t *buffer)
|
FAR const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
||||||
@@ -870,11 +911,13 @@ static ssize_t is25xp_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbyt
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MTD_BYTE_WRITE */
|
#endif /* CONFIG_MTD_BYTE_WRITE */
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_ioctl
|
* Name: is25xp_ioctl
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int is25xp_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int is25xp_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg)
|
||||||
{
|
{
|
||||||
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
FAR struct is25xp_dev_s *priv = (FAR struct is25xp_dev_s *)dev;
|
||||||
int ret = -EINVAL; /* Assume good command with bad parameters */
|
int ret = -EINVAL; /* Assume good command with bad parameters */
|
||||||
@@ -885,16 +928,18 @@ static int is25xp_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
{
|
{
|
||||||
case MTDIOC_GEOMETRY:
|
case MTDIOC_GEOMETRY:
|
||||||
{
|
{
|
||||||
FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg);
|
FAR struct mtd_geometry_s *geo =
|
||||||
|
(FAR struct mtd_geometry_s *)((uintptr_t)arg);
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an array
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* of fixed size blocks. That is most likely not true, but the
|
||||||
* appear so.
|
* client will expect the device logic to do whatever is
|
||||||
|
* necessary to make it appear so.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = (1 << priv->pageshift);
|
geo->blocksize = (1 << priv->pageshift);
|
||||||
@@ -929,11 +974,11 @@ static int is25xp_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: is25xp_initialize
|
* Name: is25xp_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
@@ -941,7 +986,7 @@ static int is25xp_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
* in the file system, but are created as instances that can be bound to
|
* in the file system, but are created as instances that can be bound to
|
||||||
* other functions (such as a block or character driver front end).
|
* other functions (such as a block or character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *is25xp_initialize(FAR struct spi_dev_s *dev)
|
FAR struct mtd_dev_s *is25xp_initialize(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -953,8 +998,8 @@ FAR struct mtd_dev_s *is25xp_initialize(FAR struct spi_dev_s *dev)
|
|||||||
/* Allocate a state structure (we allocate the structure instead of using
|
/* Allocate a state structure (we allocate the structure instead of using
|
||||||
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
||||||
* The current implementation would handle only one FLASH part per SPI
|
* The current implementation would handle only one FLASH part per SPI
|
||||||
* device (only because of the SPIDEV_FLASH(0) definition) and so would have
|
* device (only because of the SPIDEV_FLASH(0) definition) and so would
|
||||||
* to be extended to handle multiple FLASH parts on the same SPI bus.
|
* have to be extended to handle multiple FLASH parts on the same SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv = (FAR struct is25xp_dev_s *)kmm_zalloc(sizeof(struct is25xp_dev_s));
|
priv = (FAR struct is25xp_dev_s *)kmm_zalloc(sizeof(struct is25xp_dev_s));
|
||||||
@@ -985,7 +1030,9 @@ FAR struct mtd_dev_s *is25xp_initialize(FAR struct spi_dev_s *dev)
|
|||||||
ret = is25xp_readid(priv);
|
ret = is25xp_readid(priv);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
/* Unrecognized! Discard all of that work we just did and return NULL */
|
/* Unrecognized! Discard all of that work we just did and
|
||||||
|
* return NULL
|
||||||
|
*/
|
||||||
|
|
||||||
ferr("ERROR: Unrecognized\n");
|
ferr("ERROR: Unrecognized\n");
|
||||||
kmm_free(priv);
|
kmm_free(priv);
|
||||||
@@ -993,7 +1040,9 @@ FAR struct mtd_dev_s *is25xp_initialize(FAR struct spi_dev_s *dev)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Make sure that the FLASH is unprotected so that we can write into it */
|
/* Make sure that the FLASH is unprotected so that we can
|
||||||
|
* write into it
|
||||||
|
*/
|
||||||
|
|
||||||
is25xp_unprotect(priv);
|
is25xp_unprotect(priv);
|
||||||
}
|
}
|
||||||
|
|||||||
+137
-100
@@ -1,7 +1,7 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/m25px.c
|
* drivers/mtd/m25px.c
|
||||||
* Driver for SPI-based M25P1 (128Kbit), M25P64 (32Mbit), M25P64 (64Mbit), and
|
* Driver for SPI-based M25P1 (128Kbit), M25P64 (32Mbit), M25P64 (64Mbit),
|
||||||
* M25P128 (128Mbit) FLASH (and compatible).
|
* and M25P128 (128Mbit) FLASH (and compatible).
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009-2011, 2013, 2017 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
@@ -33,11 +33,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
@@ -56,17 +56,18 @@
|
|||||||
#include <nuttx/spi/spi.h>
|
#include <nuttx/spi/spi.h>
|
||||||
#include <nuttx/mtd/mtd.h>
|
#include <nuttx/mtd/mtd.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Configuration ********************************************************************/
|
/* Configuration ************************************************************/
|
||||||
|
|
||||||
/* Per the data sheet, M25P10 parts can be driven with either SPI mode 0 (CPOL=0 and
|
/* Per the data sheet, M25P10 parts can be driven with either SPI mode 0
|
||||||
* CPHA=0) or mode 3 (CPOL=1 and CPHA=1). But I have heard that other devices can
|
* (CPOL=0 and CPHA=0) or mode 3 (CPOL=1 and CPHA=1). But I have heard that
|
||||||
* operated in mode 0 or 1. So you may need to specify CONFIG_M25P_SPIMODE to
|
* other devices can operated in mode 0 or 1.
|
||||||
* select the best mode for your device. If CONFIG_M25P_SPIMODE is not defined,
|
* So you may need to specify CONFIG_M25P_SPIMODE to
|
||||||
* mode 0 will be used.
|
* select the best mode for your device.
|
||||||
|
* If CONFIG_M25P_SPIMODE is not defined, mode 0 will be used.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_M25P_SPIMODE
|
#ifndef CONFIG_M25P_SPIMODE
|
||||||
@@ -77,9 +78,10 @@
|
|||||||
# define CONFIG_M25P_SPIFREQUENCY 20000000
|
# define CONFIG_M25P_SPIFREQUENCY 20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Various manufacturers may have produced the parts. 0x20 is the manufacturer ID
|
/* Various manufacturers may have produced the parts.
|
||||||
* for the STMicro MP25x serial FLASH. If, for example, you are using the a Macronix
|
* 0x20 is the manufacturer ID for the STMicro MP25x serial FLASH.
|
||||||
* International MX25 serial FLASH, the correct manufacturer ID would be 0xc2.
|
* If, for example, you are using the a Macronix International MX25
|
||||||
|
* serial FLASH, the correct manufacturer ID would be 0xc2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_M25P_MANUFACTURER
|
#ifndef CONFIG_M25P_MANUFACTURER
|
||||||
@@ -94,7 +96,7 @@
|
|||||||
# define CONFIG_MT25Q_MEMORY_TYPE 0xBA
|
# define CONFIG_MT25Q_MEMORY_TYPE 0xBA
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* M25P Registers *******************************************************************/
|
/* M25P Registers ***********************************************************/
|
||||||
|
|
||||||
/* Identification register values */
|
/* Identification register values */
|
||||||
|
|
||||||
@@ -227,9 +229,9 @@
|
|||||||
|
|
||||||
#define M25P_DUMMY 0xa5
|
#define M25P_DUMMY 0xa5
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
||||||
* must appear at the beginning of the definition so that you can freely
|
* must appear at the beginning of the definition so that you can freely
|
||||||
@@ -249,9 +251,9 @@ struct m25p_dev_s
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
|
|
||||||
@@ -260,38 +262,51 @@ static inline void m25p_unlock(FAR struct spi_dev_s *dev);
|
|||||||
static inline int m25p_readid(struct m25p_dev_s *priv);
|
static inline int m25p_readid(struct m25p_dev_s *priv);
|
||||||
static void m25p_waitwritecomplete(struct m25p_dev_s *priv);
|
static void m25p_waitwritecomplete(struct m25p_dev_s *priv);
|
||||||
static void m25p_writeenable(struct m25p_dev_s *priv);
|
static void m25p_writeenable(struct m25p_dev_s *priv);
|
||||||
static inline void m25p_sectorerase(struct m25p_dev_s *priv, off_t offset,
|
static inline void m25p_sectorerase(struct m25p_dev_s *priv,
|
||||||
|
off_t offset,
|
||||||
uint8_t type);
|
uint8_t type);
|
||||||
static inline int m25p_bulkerase(struct m25p_dev_s *priv);
|
static inline int m25p_bulkerase(struct m25p_dev_s *priv);
|
||||||
static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const uint8_t *buffer,
|
static inline void m25p_pagewrite(struct m25p_dev_s *priv,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
off_t offset);
|
off_t offset);
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int m25p_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
static int m25p_erase(FAR struct mtd_dev_s *dev,
|
||||||
static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf);
|
size_t nblocks);
|
||||||
static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t m25p_bread(FAR struct mtd_dev_s *dev,
|
||||||
size_t nblocks, FAR const uint8_t *buf);
|
off_t startblock,
|
||||||
static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
size_t nblocks,
|
||||||
|
FAR uint8_t *buf);
|
||||||
|
static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
|
FAR const uint8_t *buf);
|
||||||
|
static ssize_t m25p_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset, size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
static ssize_t m25p_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t m25p_write(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR const uint8_t *buffer);
|
FAR const uint8_t *buffer);
|
||||||
#endif
|
#endif
|
||||||
static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int m25p_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_lock
|
* Name: m25p_lock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void m25p_lock(FAR struct spi_dev_s *dev)
|
static void m25p_lock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -299,16 +314,18 @@ static void m25p_lock(FAR struct spi_dev_s *dev)
|
|||||||
* lock SPI to have exclusive access to the buses for a sequence of
|
* lock SPI to have exclusive access to the buses for a sequence of
|
||||||
* transfers. The bus should be locked before the chip is selected.
|
* transfers. The bus should be locked before the chip is selected.
|
||||||
*
|
*
|
||||||
* This is a blocking call and will not return until we have exclusive access to
|
* This is a blocking call and will not return until we have exclusive
|
||||||
* the SPI bus. We will retain that exclusive access until the bus is unlocked.
|
* access to the SPI bus. We will retain that exclusive access until the
|
||||||
|
* bus is unlocked.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPI_LOCK(dev, true);
|
SPI_LOCK(dev, true);
|
||||||
|
|
||||||
/* After locking the SPI bus, the we also need call the setfrequency, setbits, and
|
/* After locking the SPI bus, the we also need call the setfrequency,
|
||||||
* setmode methods to make sure that the SPI is properly configured for the device.
|
* setbits, and setmode methods to make sure that the SPI is properly
|
||||||
* If the SPI bus is being shared, then it may have been left in an incompatible
|
* configured for the device.
|
||||||
* state.
|
* If the SPI bus is being shared, then it may have been left in an
|
||||||
|
* incompatible state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
SPI_SETMODE(dev, CONFIG_M25P_SPIMODE);
|
SPI_SETMODE(dev, CONFIG_M25P_SPIMODE);
|
||||||
@@ -317,18 +334,18 @@ static void m25p_lock(FAR struct spi_dev_s *dev)
|
|||||||
SPI_SETFREQUENCY(dev, CONFIG_M25P_SPIFREQUENCY);
|
SPI_SETFREQUENCY(dev, CONFIG_M25P_SPIFREQUENCY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_unlock
|
* Name: m25p_unlock
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void m25p_unlock(FAR struct spi_dev_s *dev)
|
static inline void m25p_unlock(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
SPI_LOCK(dev, false);
|
SPI_LOCK(dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_readid
|
* Name: m25p_readid
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int m25p_readid(struct m25p_dev_s *priv)
|
static inline int m25p_readid(struct m25p_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -463,9 +480,9 @@ static inline int m25p_readid(struct m25p_dev_s *priv)
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_waitwritecomplete
|
* Name: m25p_waitwritecomplete
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void m25p_waitwritecomplete(struct m25p_dev_s *priv)
|
static void m25p_waitwritecomplete(struct m25p_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -483,7 +500,9 @@ static void m25p_waitwritecomplete(struct m25p_dev_s *priv)
|
|||||||
|
|
||||||
SPI_SEND(priv->dev, M25P_RDSR);
|
SPI_SEND(priv->dev, M25P_RDSR);
|
||||||
|
|
||||||
/* Send a dummy byte to generate the clock needed to shift out the status */
|
/* Send a dummy byte to generate the clock needed to shift out the
|
||||||
|
* status
|
||||||
|
*/
|
||||||
|
|
||||||
status = SPI_SEND(priv->dev, M25P_DUMMY);
|
status = SPI_SEND(priv->dev, M25P_DUMMY);
|
||||||
|
|
||||||
@@ -491,9 +510,10 @@ static void m25p_waitwritecomplete(struct m25p_dev_s *priv)
|
|||||||
|
|
||||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
||||||
|
|
||||||
/* Given that writing could take up to few tens of milliseconds, and erasing
|
/* Given that writing could take up to few tens of milliseconds, and
|
||||||
* could take more. The following short delay in the "busy" case will allow
|
* erasing could take more.
|
||||||
* other peripherals to access the SPI bus.
|
* The following short delay in the "busy" case will allow other
|
||||||
|
* peripherals to access the SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((status & M25P_SR_WIP) != 0)
|
if ((status & M25P_SR_WIP) != 0)
|
||||||
@@ -508,9 +528,9 @@ static void m25p_waitwritecomplete(struct m25p_dev_s *priv)
|
|||||||
finfo("Complete\n");
|
finfo("Complete\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_writeenable
|
* Name: m25p_writeenable
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void m25p_writeenable(struct m25p_dev_s *priv)
|
static void m25p_writeenable(struct m25p_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -528,11 +548,13 @@ static void m25p_writeenable(struct m25p_dev_s *priv)
|
|||||||
finfo("Enabled\n");
|
finfo("Enabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_sectorerase
|
* Name: m25p_sectorerase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector, uint8_t type)
|
static void m25p_sectorerase(struct m25p_dev_s *priv,
|
||||||
|
off_t sector,
|
||||||
|
uint8_t type)
|
||||||
{
|
{
|
||||||
off_t offset;
|
off_t offset;
|
||||||
|
|
||||||
@@ -586,9 +608,9 @@ static void m25p_sectorerase(struct m25p_dev_s *priv, off_t sector, uint8_t type
|
|||||||
finfo("Erased\n");
|
finfo("Erased\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_bulkerase
|
* Name: m25p_bulkerase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline int m25p_bulkerase(struct m25p_dev_s *priv)
|
static inline int m25p_bulkerase(struct m25p_dev_s *priv)
|
||||||
{
|
{
|
||||||
@@ -621,11 +643,12 @@ static inline int m25p_bulkerase(struct m25p_dev_s *priv)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_pagewrite
|
* Name: m25p_pagewrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const uint8_t *buffer,
|
static inline void m25p_pagewrite(struct m25p_dev_s *priv,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
off_t page)
|
off_t page)
|
||||||
{
|
{
|
||||||
off_t offset = page << priv->pageshift;
|
off_t offset = page << priv->pageshift;
|
||||||
@@ -668,13 +691,15 @@ static inline void m25p_pagewrite(struct m25p_dev_s *priv, FAR const uint8_t *bu
|
|||||||
finfo("Written\n");
|
finfo("Written\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_bytewrite
|
* Name: m25p_bytewrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
static inline void m25p_bytewrite(struct m25p_dev_s *priv, FAR const uint8_t *buffer,
|
static inline void m25p_bytewrite(struct m25p_dev_s *priv,
|
||||||
off_t offset, uint16_t count)
|
FAR const uint8_t *buffer,
|
||||||
|
off_t offset,
|
||||||
|
uint16_t count)
|
||||||
{
|
{
|
||||||
finfo("offset: %08lx count:%d\n", (long)offset, count);
|
finfo("offset: %08lx count:%d\n", (long)offset, count);
|
||||||
|
|
||||||
@@ -715,11 +740,13 @@ static inline void m25p_bytewrite(struct m25p_dev_s *priv, FAR const uint8_t *bu
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_erase
|
* Name: m25p_erase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int m25p_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
static int m25p_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev;
|
FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev;
|
||||||
size_t blocksleft = nblocks;
|
size_t blocksleft = nblocks;
|
||||||
@@ -782,9 +809,9 @@ static int m25p_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblock
|
|||||||
return (int)nblocks;
|
return (int)nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_bread
|
* Name: m25p_bread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks,
|
size_t nblocks,
|
||||||
@@ -809,9 +836,9 @@ static ssize_t m25p_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
return (int)nbytes;
|
return (int)nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_bwrite
|
* Name: m25p_bwrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks,
|
size_t nblocks,
|
||||||
@@ -837,11 +864,13 @@ static ssize_t m25p_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
return nblocks;
|
return nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_read
|
* Name: m25p_read
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t m25p_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev;
|
FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev;
|
||||||
@@ -889,12 +918,14 @@ static ssize_t m25p_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_write
|
* Name: m25p_write
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
static ssize_t m25p_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t m25p_write(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR const uint8_t *buffer)
|
FAR const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev;
|
FAR struct m25p_dev_s *priv = (FAR struct m25p_dev_s *)dev;
|
||||||
@@ -963,9 +994,9 @@ static ssize_t m25p_write(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MTD_BYTE_WRITE */
|
#endif /* CONFIG_MTD_BYTE_WRITE */
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_ioctl
|
* Name: m25p_ioctl
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@@ -982,13 +1013,15 @@ static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
((uintptr_t)arg);
|
((uintptr_t)arg);
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an array
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* of fixed size blocks.
|
||||||
* appear so.
|
* That is most likely not true, but the client will expect the
|
||||||
|
* device logic to do whatever is necessary to make it appear
|
||||||
|
* so.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = (1 << priv->pageshift);
|
geo->blocksize = (1 << priv->pageshift);
|
||||||
@@ -996,7 +1029,8 @@ static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
if (priv->subsectorshift > 0)
|
if (priv->subsectorshift > 0)
|
||||||
{
|
{
|
||||||
geo->erasesize = (1 << priv->subsectorshift);
|
geo->erasesize = (1 << priv->subsectorshift);
|
||||||
geo->neraseblocks = priv->nsectors * (1 << (priv->sectorshift -
|
geo->neraseblocks = priv->nsectors *
|
||||||
|
(1 << (priv->sectorshift -
|
||||||
priv->subsectorshift));
|
priv->subsectorshift));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1035,19 +1069,20 @@ static int m25p_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: m25p_initialize
|
* Name: m25p_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Create an initialize MTD device instance. MTD devices are not registered
|
* Create an initialize MTD device instance.
|
||||||
* in the file system, but are created as instances that can be bound to
|
* MTD devices are not registered in the file system, but are created as
|
||||||
* other functions (such as a block or character driver front end).
|
* instances that can be bound to other functions (such as a block or
|
||||||
|
* character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev)
|
FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev)
|
||||||
{
|
{
|
||||||
@@ -1059,8 +1094,8 @@ FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev)
|
|||||||
/* Allocate a state structure (we allocate the structure instead of using
|
/* Allocate a state structure (we allocate the structure instead of using
|
||||||
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
||||||
* The current implementation would handle only one FLASH part per SPI
|
* The current implementation would handle only one FLASH part per SPI
|
||||||
* device (only because of the SPIDEV_FLASH(0) definition) and so would have
|
* device (only because of the SPIDEV_FLASH(0) definition) and so would
|
||||||
* to be extended to handle multiple FLASH parts on the same SPI bus.
|
* have to be extended to handle multiple FLASH parts on the same SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv = (FAR struct m25p_dev_s *)kmm_zalloc(sizeof(struct m25p_dev_s));
|
priv = (FAR struct m25p_dev_s *)kmm_zalloc(sizeof(struct m25p_dev_s));
|
||||||
@@ -1090,7 +1125,9 @@ FAR struct mtd_dev_s *m25p_initialize(FAR struct spi_dev_s *dev)
|
|||||||
ret = m25p_readid(priv);
|
ret = m25p_readid(priv);
|
||||||
if (ret != OK)
|
if (ret != OK)
|
||||||
{
|
{
|
||||||
/* Unrecognized! Discard all of that work we just did and return NULL */
|
/* Unrecognized!
|
||||||
|
* Discard all of that work we just did and return NULL
|
||||||
|
*/
|
||||||
|
|
||||||
ferr("ERROR: Unrecognized\n");
|
ferr("ERROR: Unrecognized\n");
|
||||||
kmm_free(priv);
|
kmm_free(priv);
|
||||||
|
|||||||
+65
-78
@@ -1,4 +1,4 @@
|
|||||||
/**************************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/mtd_modeltab.c
|
* drivers/mtd/mtd_modeltab.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2013 Gregory Nutt. All rights reserved.
|
||||||
@@ -37,11 +37,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
**************************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/**************************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
**************************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
#include <nuttx/mtd/nand_config.h>
|
#include <nuttx/mtd/nand_config.h>
|
||||||
@@ -49,19 +49,19 @@
|
|||||||
#include <nuttx/mtd/nand_scheme.h>
|
#include <nuttx/mtd/nand_scheme.h>
|
||||||
#include <nuttx/mtd/nand_model.h>
|
#include <nuttx/mtd/nand_model.h>
|
||||||
|
|
||||||
/**************************************************************************************************
|
/****************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
**************************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* List of NandFlash models which can be recognized by the software */
|
/* List of NandFlash models which can be recognized by the software */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* ID OPTIONS PAGE SPARE DEV BLOCK | SCHEME
|
||||||
|
* SIZE SIZE SIZE SIZE |
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
const struct nand_model_s g_nandmodels[NAND_NMODELS] =
|
const struct nand_model_s g_nandmodels[NAND_NMODELS] =
|
||||||
{
|
{
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------
|
|
||||||
* | ID | OPTIONS | PAGE | SPARE | DEV | BLOCK | SCHEME
|
|
||||||
* | | | SIZE | SIZE | SIZE | SIZE |
|
|
||||||
*----------|------------------------------+------+-------+------+-------+------------------------*/
|
|
||||||
|
|
||||||
{0x6e, NANDMODEL_DATAWIDTH8, 256, 0, 1, 4, &g_nand_sparescheme256},
|
{0x6e, NANDMODEL_DATAWIDTH8, 256, 0, 1, 4, &g_nand_sparescheme256},
|
||||||
{0x64, NANDMODEL_DATAWIDTH8, 256, 0, 2, 4, &g_nand_sparescheme256},
|
{0x64, NANDMODEL_DATAWIDTH8, 256, 0, 2, 4, &g_nand_sparescheme256},
|
||||||
{0x68, NANDMODEL_DATAWIDTH8, 4096, 0, 224, 1024, &g_nand_sparescheme4096},
|
{0x68, NANDMODEL_DATAWIDTH8, 4096, 0, 224, 1024, &g_nand_sparescheme4096},
|
||||||
@@ -73,37 +73,22 @@ const struct nand_model_s g_nandmodels[NAND_NMODELS] =
|
|||||||
{0xe3, NANDMODEL_DATAWIDTH8, 512, 0, 4, 8, &g_nand_sparescheme512},
|
{0xe3, NANDMODEL_DATAWIDTH8, 512, 0, 4, 8, &g_nand_sparescheme512},
|
||||||
{0xe5, NANDMODEL_DATAWIDTH8, 512, 0, 4, 8, &g_nand_sparescheme512},
|
{0xe5, NANDMODEL_DATAWIDTH8, 512, 0, 4, 8, &g_nand_sparescheme512},
|
||||||
{0xd6, NANDMODEL_DATAWIDTH8, 512, 0, 8, 8, &g_nand_sparescheme512},
|
{0xd6, NANDMODEL_DATAWIDTH8, 512, 0, 8, 8, &g_nand_sparescheme512},
|
||||||
|
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
|
||||||
|
|
||||||
{0x39, NANDMODEL_DATAWIDTH8, 512, 0, 8, 8, &g_nand_sparescheme512},
|
{0x39, NANDMODEL_DATAWIDTH8, 512, 0, 8, 8, &g_nand_sparescheme512},
|
||||||
{0xe6, NANDMODEL_DATAWIDTH8, 512, 0, 8, 8, &g_nand_sparescheme512},
|
{0xe6, NANDMODEL_DATAWIDTH8, 512, 0, 8, 8, &g_nand_sparescheme512},
|
||||||
{0x49, NANDMODEL_DATAWIDTH16, 512, 0, 8, 8, &g_nand_sparescheme512},
|
{0x49, NANDMODEL_DATAWIDTH16, 512, 0, 8, 8, &g_nand_sparescheme512},
|
||||||
{0x59, NANDMODEL_DATAWIDTH16, 512, 0, 8, 8, &g_nand_sparescheme512},
|
{0x59, NANDMODEL_DATAWIDTH16, 512, 0, 8, 8, &g_nand_sparescheme512},
|
||||||
|
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
|
||||||
|
|
||||||
{0x33, NANDMODEL_DATAWIDTH8, 512, 0, 16, 16, &g_nand_sparescheme512},
|
{0x33, NANDMODEL_DATAWIDTH8, 512, 0, 16, 16, &g_nand_sparescheme512},
|
||||||
{0x73, NANDMODEL_DATAWIDTH8, 512, 0, 16, 16, &g_nand_sparescheme512},
|
{0x73, NANDMODEL_DATAWIDTH8, 512, 0, 16, 16, &g_nand_sparescheme512},
|
||||||
{0x43, NANDMODEL_DATAWIDTH16, 512, 0, 16, 16, &g_nand_sparescheme512},
|
{0x43, NANDMODEL_DATAWIDTH16, 512, 0, 16, 16, &g_nand_sparescheme512},
|
||||||
{0x53, NANDMODEL_DATAWIDTH16, 512, 0, 16, 16, &g_nand_sparescheme512},
|
{0x53, NANDMODEL_DATAWIDTH16, 512, 0, 16, 16, &g_nand_sparescheme512},
|
||||||
|
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
|
||||||
|
|
||||||
{0x35, NANDMODEL_DATAWIDTH8, 512, 0, 32, 16, &g_nand_sparescheme512},
|
{0x35, NANDMODEL_DATAWIDTH8, 512, 0, 32, 16, &g_nand_sparescheme512},
|
||||||
{0x75, NANDMODEL_DATAWIDTH8, 512, 0, 32, 16, &g_nand_sparescheme512},
|
{0x75, NANDMODEL_DATAWIDTH8, 512, 0, 32, 16, &g_nand_sparescheme512},
|
||||||
{0x45, NANDMODEL_DATAWIDTH16, 512, 0, 32, 16, &g_nand_sparescheme512},
|
{0x45, NANDMODEL_DATAWIDTH16, 512, 0, 32, 16, &g_nand_sparescheme512},
|
||||||
{0x55, NANDMODEL_DATAWIDTH16, 512, 0, 32, 16, &g_nand_sparescheme512},
|
{0x55, NANDMODEL_DATAWIDTH16, 512, 0, 32, 16, &g_nand_sparescheme512},
|
||||||
|
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
|
||||||
|
|
||||||
{0x36, NANDMODEL_DATAWIDTH8, 512, 0, 64, 16, &g_nand_sparescheme512},
|
{0x36, NANDMODEL_DATAWIDTH8, 512, 0, 64, 16, &g_nand_sparescheme512},
|
||||||
{0x76, NANDMODEL_DATAWIDTH8, 512, 0, 64, 16, &g_nand_sparescheme512},
|
{0x76, NANDMODEL_DATAWIDTH8, 512, 0, 64, 16, &g_nand_sparescheme512},
|
||||||
{0x46, NANDMODEL_DATAWIDTH16, 512, 0, 64, 16, &g_nand_sparescheme512},
|
{0x46, NANDMODEL_DATAWIDTH16, 512, 0, 64, 16, &g_nand_sparescheme512},
|
||||||
{0x56, NANDMODEL_DATAWIDTH16, 512, 0, 64, 16, &g_nand_sparescheme512},
|
{0x56, NANDMODEL_DATAWIDTH16, 512, 0, 64, 16, &g_nand_sparescheme512},
|
||||||
|
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
|
||||||
|
|
||||||
{0x78, NANDMODEL_DATAWIDTH8, 512, 0, 128, 16, &g_nand_sparescheme512},
|
{0x78, NANDMODEL_DATAWIDTH8, 512, 0, 128, 16, &g_nand_sparescheme512},
|
||||||
{0x39, NANDMODEL_DATAWIDTH8, 512, 0, 128, 16, &g_nand_sparescheme512},
|
{0x39, NANDMODEL_DATAWIDTH8, 512, 0, 128, 16, &g_nand_sparescheme512},
|
||||||
{0x79, NANDMODEL_DATAWIDTH8, 512, 0, 128, 16, &g_nand_sparescheme512},
|
{0x79, NANDMODEL_DATAWIDTH8, 512, 0, 128, 16, &g_nand_sparescheme512},
|
||||||
@@ -111,60 +96,62 @@ const struct nand_model_s g_nandmodels[NAND_NMODELS] =
|
|||||||
{0x49, NANDMODEL_DATAWIDTH16, 512, 0, 128, 16, &g_nand_sparescheme512},
|
{0x49, NANDMODEL_DATAWIDTH16, 512, 0, 128, 16, &g_nand_sparescheme512},
|
||||||
{0x74, NANDMODEL_DATAWIDTH16, 512, 0, 128, 16, &g_nand_sparescheme512},
|
{0x74, NANDMODEL_DATAWIDTH16, 512, 0, 128, 16, &g_nand_sparescheme512},
|
||||||
{0x59, NANDMODEL_DATAWIDTH16, 512, 0, 128, 16, &g_nand_sparescheme512},
|
{0x59, NANDMODEL_DATAWIDTH16, 512, 0, 128, 16, &g_nand_sparescheme512},
|
||||||
|
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
|
||||||
|
|
||||||
{0x71, NANDMODEL_DATAWIDTH8, 512, 0, 256, 16, &g_nand_sparescheme512},
|
{0x71, NANDMODEL_DATAWIDTH8, 512, 0, 256, 16, &g_nand_sparescheme512},
|
||||||
|
|
||||||
/* Large blocks devices. Parameters must be fetched from the extended I */
|
/* Large blocks devices. Parameters must be fetched from the extended I */
|
||||||
|
|
||||||
#define OPTIONS NANDMODEL_COPYBACK
|
#define OPTIONS NANDMODEL_COPYBACK
|
||||||
|
{0xa2, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------
|
0, 0, 64, 0, &g_nand_sparescheme2048},
|
||||||
* | ID | OPTIONS | PAGE | SPARE | DEV | BLOCK | SCHEME
|
{0xf2, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
* | | | SIZE | SIZE | SIZE | SIZE |
|
0, 0, 64, 0, &g_nand_sparescheme2048},
|
||||||
*----------|------------------------------+------+-------+------+-------+------------------------*/
|
{0xb2, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
|
0, 0, 64, 0, &g_nand_sparescheme2048},
|
||||||
{0xA2, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 64, 0, &g_nand_sparescheme2048},
|
{0xc2, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0xF2, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 64, 0, &g_nand_sparescheme2048},
|
0, 0, 64, 0, &g_nand_sparescheme2048},
|
||||||
{0xB2, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 64, 0, &g_nand_sparescheme2048},
|
{0xa1, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
{0xC2, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 64, 0, &g_nand_sparescheme2048},
|
0, 0, 128, 0, &g_nand_sparescheme2048},
|
||||||
|
{0xf1, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
0, 0, 128, 0, &g_nand_sparescheme2048},
|
||||||
|
{0xb1, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0xA1, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 128, 0, &g_nand_sparescheme2048},
|
0, 0, 128, 0, &g_nand_sparescheme2048},
|
||||||
{0xF1, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 128, 0, &g_nand_sparescheme2048},
|
{0xc1, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0xB1, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 128, 0, &g_nand_sparescheme2048},
|
0, 0, 128, 0, &g_nand_sparescheme2048},
|
||||||
{0xC1, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 128, 0, &g_nand_sparescheme2048},
|
{0xaa, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
|
0, 0, 256, 0, &g_nand_sparescheme2048},
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
{0xda, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
|
0, 0, 256, 0, &g_nand_sparescheme2048},
|
||||||
{0xAA, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 256, 0, &g_nand_sparescheme2048},
|
{0xba, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0xDA, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 256, 0, &g_nand_sparescheme2048},
|
0, 0, 256, 0, &g_nand_sparescheme2048},
|
||||||
{0xBA, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 256, 0, &g_nand_sparescheme2048},
|
{0xca, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0xCA, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 256, 0, &g_nand_sparescheme2048},
|
0, 0, 256, 0, &g_nand_sparescheme2048},
|
||||||
|
{0xac, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
0, 0, 512, 0, &g_nand_sparescheme2048},
|
||||||
|
{0xdc, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
{0xAC, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 512, 0, &g_nand_sparescheme2048},
|
0, 0, 512, 0, &g_nand_sparescheme2048},
|
||||||
{0xDC, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 512, 0, &g_nand_sparescheme2048},
|
{0xbc, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0xBC, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 512, 0, &g_nand_sparescheme2048},
|
0, 0, 512, 0, &g_nand_sparescheme2048},
|
||||||
{0xCC, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 512, 0, &g_nand_sparescheme2048},
|
{0xcc, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
|
0, 0, 512, 0, &g_nand_sparescheme2048},
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
{0xa3, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
|
0, 0, 1024, 0, &g_nand_sparescheme2048},
|
||||||
{0xA3, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 1024, 0, &g_nand_sparescheme2048},
|
{0xd3, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
{0xD3, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 1024, 0, &g_nand_sparescheme2048},
|
0, 0, 1024, 0, &g_nand_sparescheme2048},
|
||||||
{0xB3, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 1024, 0, &g_nand_sparescheme2048},
|
{0xb3, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0xC3, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 1024, 0, &g_nand_sparescheme2048},
|
0, 0, 1024, 0, &g_nand_sparescheme2048},
|
||||||
|
{0xd3, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
0, 0, 1024, 0, &g_nand_sparescheme2048},
|
||||||
|
{0xa5, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
{0xA5, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 2048, 0, &g_nand_sparescheme2048},
|
0, 0, 2048, 0, &g_nand_sparescheme2048},
|
||||||
{0xD5, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 2048, 0, &g_nand_sparescheme2048},
|
{0xd5, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
{0xB5, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 2048, 0, &g_nand_sparescheme2048},
|
0, 0, 2048, 0, &g_nand_sparescheme2048},
|
||||||
{0xC5, NANDMODEL_DATAWIDTH16 | OPTIONS, 0, 0, 2048, 0, &g_nand_sparescheme2048},
|
{0xb5, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
{0x38, NANDMODEL_DATAWIDTH8 | OPTIONS, 0, 0, 1024, 0, &g_nand_sparescheme4096}
|
0, 0, 2048, 0, &g_nand_sparescheme2048},
|
||||||
|
{0xc5, NANDMODEL_DATAWIDTH16 | OPTIONS,
|
||||||
/*----------|------------------------------+------+-------+------+-------+------------------------*/
|
0, 0, 2048, 0, &g_nand_sparescheme2048},
|
||||||
|
{0x38, NANDMODEL_DATAWIDTH8 | OPTIONS,
|
||||||
|
0, 0, 1024, 0, &g_nand_sparescheme4096}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|||||||
@@ -97,7 +97,11 @@ int nandecc_readpage(FAR struct nand_dev_s *nand, off_t block,
|
|||||||
unsigned int sparesize;
|
unsigned int sparesize;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
finfo("block=%d page=%d data=%p spare=%d\n", (int)block, page, data, spare);
|
finfo("block=%d page=%d data=%p spare=%d\n",
|
||||||
|
(int)block,
|
||||||
|
page,
|
||||||
|
data,
|
||||||
|
spare);
|
||||||
|
|
||||||
/* Get convenience pointers */
|
/* Get convenience pointers */
|
||||||
|
|
||||||
@@ -189,7 +193,11 @@ int nandecc_writepage(FAR struct nand_dev_s *nand, off_t block,
|
|||||||
unsigned int sparesize;
|
unsigned int sparesize;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
finfo("block=%d page=%d data=%p spare=%d\n", (int)block, page, data, spare);
|
finfo("block=%d page=%d data=%p spare=%d\n",
|
||||||
|
(int)block,
|
||||||
|
page,
|
||||||
|
data,
|
||||||
|
spare);
|
||||||
|
|
||||||
/* Get convenience pointers */
|
/* Get convenience pointers */
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,8 @@
|
|||||||
* Input Parameters:
|
* Input Parameters:
|
||||||
* modeltab List of nand_model_s instances.
|
* modeltab List of nand_model_s instances.
|
||||||
* size Number of models in list.
|
* size Number of models in list.
|
||||||
* chipid Identifier returned by the Nand(id1|(id2<<8)|(id3<<16)|(id4<<24)).
|
* chipid Identifier returned by the Nand
|
||||||
|
* (id1|(id2<<8)|(id3<<16)|(id4<<24)).
|
||||||
* model nand_model_s instance to update with the model parameters.
|
* model nand_model_s instance to update with the model parameters.
|
||||||
*
|
*
|
||||||
* Returned Value:
|
* Returned Value:
|
||||||
|
|||||||
+98
-72
@@ -1,7 +1,7 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/mtd_rwbuffer.c
|
* drivers/mtd/mtd_rwbuffer.c
|
||||||
* MTD driver that contains another MTD driver and provides read-ahead and/or write
|
* MTD driver that contains another MTD driver and provides read-ahead
|
||||||
* buffering.
|
* and/or write buffering.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
@@ -33,11 +33,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
@@ -59,9 +59,9 @@
|
|||||||
|
|
||||||
#if defined(CONFIG_DRVR_WRITEBUFFER) || defined(CONFIG_DRVR_READAHEAD)
|
#if defined(CONFIG_DRVR_WRITEBUFFER) || defined(CONFIG_DRVR_READAHEAD)
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_DRVR_INVALIDATE
|
#ifndef CONFIG_DRVR_INVALIDATE
|
||||||
# error This driver requires CONFIG_DRVR_INVALIDATE
|
# error This driver requires CONFIG_DRVR_INVALIDATE
|
||||||
@@ -79,13 +79,14 @@
|
|||||||
# define CONFIG_MTD_NRDBLOCKS 4
|
# define CONFIG_MTD_NRDBLOCKS 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This type represents the state of the MTD device. The struct mtd_dev_s must
|
/* This type represents the state of the MTD device.
|
||||||
* appear at the beginning of the definition so that you can freely cast between
|
* The struct mtd_dev_s must appear at the beginning of the definition so
|
||||||
* pointers to struct mtd_dev_s and struct mtd_rwbuffer_s.
|
* that you can freely cast between pointers to struct mtd_dev_s and struct
|
||||||
|
* mtd_rwbuffer_s.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct mtd_rwbuffer_s
|
struct mtd_rwbuffer_s
|
||||||
@@ -96,45 +97,61 @@ struct mtd_rwbuffer_s
|
|||||||
uint16_t spb; /* Number of sectors per block */
|
uint16_t spb; /* Number of sectors per block */
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* rwbuffer callouts */
|
/* rwbuffer callouts */
|
||||||
|
|
||||||
static ssize_t mtd_reload(FAR void *dev, FAR uint8_t *buffer, off_t startblock,
|
static ssize_t mtd_reload(FAR void *dev,
|
||||||
|
FAR uint8_t *buffer,
|
||||||
|
off_t startblock,
|
||||||
size_t nblocks);
|
size_t nblocks);
|
||||||
static ssize_t mtd_flush(FAR void *dev, FAR const uint8_t *buffer, off_t startblock,
|
static ssize_t mtd_flush(FAR void *dev,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
|
off_t startblock,
|
||||||
size_t nblocks);
|
size_t nblocks);
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int mtd_erase(FAR struct mtd_dev_s *dev, off_t block, size_t nsectors);
|
static int mtd_erase(FAR struct mtd_dev_s *dev,
|
||||||
static ssize_t mtd_bread(FAR struct mtd_dev_s *dev, off_t block,
|
off_t block,
|
||||||
size_t nsectors, FAR uint8_t *buf);
|
size_t nsectors);
|
||||||
static ssize_t mtd_bwrite(FAR struct mtd_dev_s *dev, off_t block,
|
static ssize_t mtd_bread(FAR struct mtd_dev_s *dev,
|
||||||
size_t nsectors, FAR const uint8_t *buf);
|
off_t block,
|
||||||
static ssize_t mtd_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
size_t nsectors,
|
||||||
|
FAR uint8_t *buf);
|
||||||
|
static ssize_t mtd_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t block,
|
||||||
|
size_t nsectors,
|
||||||
|
FAR const uint8_t *buf);
|
||||||
|
static ssize_t mtd_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
static int mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int mtd_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_reload
|
* Name: mtd_reload
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Reload the read-ahead buffer
|
* Reload the read-ahead buffer
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t mtd_reload(FAR void *dev, FAR uint8_t *buffer, off_t startblock,
|
static ssize_t mtd_reload(FAR void *dev,
|
||||||
|
FAR uint8_t *buffer,
|
||||||
|
off_t startblock,
|
||||||
size_t nblocks)
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
||||||
@@ -145,15 +162,17 @@ static ssize_t mtd_reload(FAR void *dev, FAR uint8_t *buffer, off_t startblock,
|
|||||||
return priv->dev->bread(priv->dev, startblock, nblocks, buffer);
|
return priv->dev->bread(priv->dev, startblock, nblocks, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_flush
|
* Name: mtd_flush
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Flush the write buffer to hardware
|
* Flush the write buffer to hardware
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t mtd_flush(FAR void *dev, FAR const uint8_t *buffer, off_t startblock,
|
static ssize_t mtd_flush(FAR void *dev,
|
||||||
|
FAR const uint8_t *buffer,
|
||||||
|
off_t startblock,
|
||||||
size_t nblocks)
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
||||||
@@ -164,11 +183,13 @@ static ssize_t mtd_flush(FAR void *dev, FAR const uint8_t *buffer, off_t startbl
|
|||||||
return priv->dev->bwrite(priv->dev, startblock, nblocks, buffer);
|
return priv->dev->bwrite(priv->dev, startblock, nblocks, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_erase
|
* Name: mtd_erase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int mtd_erase(FAR struct mtd_dev_s *dev, off_t block, size_t nblocks)
|
static int mtd_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t block,
|
||||||
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
||||||
off_t sector;
|
off_t sector;
|
||||||
@@ -197,57 +218,60 @@ static int mtd_erase(FAR struct mtd_dev_s *dev, off_t block, size_t nblocks)
|
|||||||
return priv->dev->erase(priv->dev, block, nblocks);
|
return priv->dev->erase(priv->dev, block, nblocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_bread
|
* Name: mtd_bread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t mtd_bread(FAR struct mtd_dev_s *dev, off_t sector,
|
static ssize_t mtd_bread(FAR struct mtd_dev_s *dev, off_t sector,
|
||||||
size_t nsectors, FAR uint8_t *buffer)
|
size_t nsectors, FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
||||||
|
|
||||||
/* Let the rwbuffer logic do it real work. It will call out to mtd_reload if is
|
/* Let the rwbuffer logic do it real work.
|
||||||
* needs to read any data.
|
* It will call out to mtd_reload if is needs to read any data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return rwb_read(&priv->rwb, sector, nsectors, buffer);
|
return rwb_read(&priv->rwb, sector, nsectors, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_bwrite
|
* Name: mtd_bwrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t mtd_bwrite(FAR struct mtd_dev_s *dev, off_t block, size_t nsectors,
|
static ssize_t mtd_bwrite(FAR struct mtd_dev_s *dev, off_t block,
|
||||||
|
size_t nsectors,
|
||||||
FAR const uint8_t *buffer)
|
FAR const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
||||||
|
|
||||||
/* Let the rwbuffer logic do it real work. It will call out to wrb_reload it is
|
/* Let the rwbuffer logic do it real work.
|
||||||
* needs to read any data.
|
* It will call out to wrb_reload it is needs to read any data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return rwb_write(&priv->rwb, block, nsectors, buffer);
|
return rwb_write(&priv->rwb, block, nsectors, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_read
|
* Name: mtd_read
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t mtd_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t mtd_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
FAR struct mtd_rwbuffer_s *priv = (FAR struct mtd_rwbuffer_s *)dev;
|
||||||
|
|
||||||
/* Let the rwbuffer logic do it real work. It will call out to mtd_reload it is
|
/* Let the rwbuffer logic do it real work.
|
||||||
* needs to read any data.
|
* It will call out to mtd_reload it is needs to read any data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return rwb_readbytes(&priv->rwb, offset, nbytes, buffer);
|
return rwb_readbytes(&priv->rwb, offset, nbytes, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_ioctl
|
* Name: mtd_ioctl
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@@ -264,13 +288,14 @@ static int mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
((uintptr_t)arg);
|
((uintptr_t)arg);
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an array
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* of fixed size blocks. That is most likely not true, but the
|
||||||
* appear so.
|
* client will expect the device logic to do whatever is
|
||||||
|
* necessary to make it appear so.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = priv->rwb.blocksize;
|
geo->blocksize = priv->rwb.blocksize;
|
||||||
@@ -315,23 +340,23 @@ static int mtd_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mtd_rwb_initialize
|
* Name: mtd_rwb_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Create an initialized MTD device instance. This MTD driver contains another
|
* Create an initialized MTD device instance.
|
||||||
* MTD driver and converts a larger sector size to a standard 512 byte sector
|
* This MTD driver contains another MTD driver and converts a larger
|
||||||
* size.
|
* sector size to a standard 512 byte sector size.
|
||||||
*
|
*
|
||||||
* MTD devices are not registered in the file system, but are created as instances
|
* MTD devices are not registered in the file system, but are created as
|
||||||
* that can be bound to other functions (such as a block or character driver front
|
* instances that can be bound to other functions (such as a block or
|
||||||
* end).
|
* character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *mtd_rwb_initialize(FAR struct mtd_dev_s *mtd)
|
FAR struct mtd_dev_s *mtd_rwb_initialize(FAR struct mtd_dev_s *mtd)
|
||||||
{
|
{
|
||||||
@@ -354,11 +379,12 @@ FAR struct mtd_dev_s *mtd_rwb_initialize(FAR struct mtd_dev_s *mtd)
|
|||||||
/* Allocate a state structure (we allocate the structure instead of using
|
/* Allocate a state structure (we allocate the structure instead of using
|
||||||
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
||||||
* The current implementation would handle only one FLASH part per SPI
|
* The current implementation would handle only one FLASH part per SPI
|
||||||
* device (only because of the SPIDEV_FLASH(0) definition) and so would have
|
* device (only because of the SPIDEV_FLASH(0) definition) and so would
|
||||||
* to be extended to handle multiple FLASH parts on the same SPI bus.
|
* have to be extended to handle multiple FLASH parts on the same SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv = (FAR struct mtd_rwbuffer_s *)kmm_zalloc(sizeof(struct mtd_rwbuffer_s));
|
priv = (FAR struct mtd_rwbuffer_s *)
|
||||||
|
kmm_zalloc(sizeof(struct mtd_rwbuffer_s));
|
||||||
if (!priv)
|
if (!priv)
|
||||||
{
|
{
|
||||||
ferr("ERROR: Failed to allocate mtd_rwbuffer\n");
|
ferr("ERROR: Failed to allocate mtd_rwbuffer\n");
|
||||||
|
|||||||
+172
-124
File diff suppressed because it is too large
Load Diff
+94
-70
@@ -1,4 +1,4 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/mx25rxx.c
|
* drivers/mtd/mx25rxx.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 201, 2019 Gregory Nutt. All rights reserved.
|
* Copyright (C) 201, 2019 Gregory Nutt. All rights reserved.
|
||||||
@@ -34,11 +34,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
@@ -59,9 +59,9 @@
|
|||||||
#include <nuttx/spi/qspi.h>
|
#include <nuttx/spi/qspi.h>
|
||||||
#include <nuttx/mtd/mtd.h>
|
#include <nuttx/mtd/mtd.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* MX25RXX Commands */
|
/* MX25RXX Commands */
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@
|
|||||||
#define MX25R_CR_TB (1 << 3) /* Bit 3: Top/bottom selected */
|
#define MX25R_CR_TB (1 << 3) /* Bit 3: Top/bottom selected */
|
||||||
#define MX25R_CR_DC (1 << 6) /* Bit 6: Dummy cycle */
|
#define MX25R_CR_DC (1 << 6) /* Bit 6: Dummy cycle */
|
||||||
|
|
||||||
/* Cache flags **********************************************************************/
|
/* Cache flags **************************************************************/
|
||||||
|
|
||||||
#define MX25RXX_CACHE_VALID (1 << 0) /* 1=Cache has valid data */
|
#define MX25RXX_CACHE_VALID (1 << 0) /* 1=Cache has valid data */
|
||||||
#define MX25RXX_CACHE_DIRTY (1 << 1) /* 1=Cache is dirty */
|
#define MX25RXX_CACHE_DIRTY (1 << 1) /* 1=Cache is dirty */
|
||||||
@@ -164,15 +164,15 @@
|
|||||||
#define CLR_DIRTY(p) do { (p)->flags &= ~MX25RXX_CACHE_DIRTY; } while (0)
|
#define CLR_DIRTY(p) do { (p)->flags &= ~MX25RXX_CACHE_DIRTY; } while (0)
|
||||||
#define CLR_ERASED(p) do { (p)->flags &= ~MX25RXX_CACHE_ERASED; } while (0)
|
#define CLR_ERASED(p) do { (p)->flags &= ~MX25RXX_CACHE_ERASED; } while (0)
|
||||||
|
|
||||||
/* 512 byte sector support **********************************************************/
|
/* 512 byte sector support **************************************************/
|
||||||
|
|
||||||
#define MX25RXX_SECTOR512_SHIFT 9
|
#define MX25RXX_SECTOR512_SHIFT 9
|
||||||
#define MX25RXX_SECTOR512_SIZE (1 << 9)
|
#define MX25RXX_SECTOR512_SIZE (1 << 9)
|
||||||
#define MX25RXX_ERASED_STATE 0xff
|
#define MX25RXX_ERASED_STATE 0xff
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Internal state of the MTD device */
|
/* Internal state of the MTD device */
|
||||||
|
|
||||||
@@ -194,9 +194,9 @@ struct mx25rxx_dev_s
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
@@ -234,7 +234,9 @@ static void mx25rxx_write_status_config(FAR struct mx25rxx_dev_s *dev,
|
|||||||
static void mx25rxx_write_enable(FAR struct mx25rxx_dev_s *dev, bool enable);
|
static void mx25rxx_write_enable(FAR struct mx25rxx_dev_s *dev, bool enable);
|
||||||
|
|
||||||
static int mx25rxx_write_page(struct mx25rxx_dev_s *priv,
|
static int mx25rxx_write_page(struct mx25rxx_dev_s *priv,
|
||||||
FAR const uint8_t *buffer, off_t address, size_t buflen);
|
FAR const uint8_t *buffer,
|
||||||
|
off_t address,
|
||||||
|
size_t buflen);
|
||||||
static int mx25rxx_erase_sector(struct mx25rxx_dev_s *priv, off_t sector);
|
static int mx25rxx_erase_sector(struct mx25rxx_dev_s *priv, off_t sector);
|
||||||
#if 0 /* FIXME: Not used */
|
#if 0 /* FIXME: Not used */
|
||||||
static int mx25rxx_erase_block(struct mx25rxx_dev_s *priv, off_t block);
|
static int mx25rxx_erase_block(struct mx25rxx_dev_s *priv, off_t block);
|
||||||
@@ -243,15 +245,16 @@ static int mx25rxx_erase_chip(struct mx25rxx_dev_s *priv);
|
|||||||
|
|
||||||
#ifdef CONFIG_MX25RXX_SECTOR512
|
#ifdef CONFIG_MX25RXX_SECTOR512
|
||||||
static int mx25rxx_flush_cache(struct mx25rxx_dev_s *priv);
|
static int mx25rxx_flush_cache(struct mx25rxx_dev_s *priv);
|
||||||
static FAR uint8_t *mx25rxx_read_cache(struct mx25rxx_dev_s *priv, off_t sector);
|
static FAR uint8_t *mx25rxx_read_cache(struct mx25rxx_dev_s *priv,
|
||||||
|
off_t sector);
|
||||||
static void mx25rxx_erase_cache(struct mx25rxx_dev_s *priv, off_t sector);
|
static void mx25rxx_erase_cache(struct mx25rxx_dev_s *priv, off_t sector);
|
||||||
static int mx25rxx_write_cache(FAR struct mx25rxx_dev_s *priv,
|
static int mx25rxx_write_cache(FAR struct mx25rxx_dev_s *priv,
|
||||||
FAR const uint8_t *buffer, off_t sector, size_t nsectors);
|
FAR const uint8_t *buffer, off_t sector, size_t nsectors);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
void mx25rxx_lock(FAR struct qspi_dev_s *qspi, bool read)
|
void mx25rxx_lock(FAR struct qspi_dev_s *qspi, bool read)
|
||||||
{
|
{
|
||||||
@@ -259,23 +262,24 @@ void mx25rxx_lock(FAR struct qspi_dev_s *qspi, bool read)
|
|||||||
* lock SPI to have exclusive access to the buses for a sequence of
|
* lock SPI to have exclusive access to the buses for a sequence of
|
||||||
* transfers. The bus should be locked before the chip is selected.
|
* transfers. The bus should be locked before the chip is selected.
|
||||||
*
|
*
|
||||||
* This is a blocking call and will not return until we have exclusive access
|
* This is a blocking call and will not return until we have exclusive
|
||||||
* to the SPI bus. We will retain that exclusive access until the bus is
|
* access to the SPI bus. We will retain that exclusive access until the
|
||||||
* unlocked.
|
* bus is unlocked.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QSPI_LOCK(qspi, true);
|
QSPI_LOCK(qspi, true);
|
||||||
|
|
||||||
/* After locking the SPI bus, the we also need call the setfrequency, setbits
|
/* After locking the SPI bus, the we also need call the setfrequency,
|
||||||
* and setmode methods to make sure that the SPI is properly configured for
|
* setbits and setmode methods to make sure that the SPI is properly
|
||||||
* the device. If the SPI bus is being shared, then it may have been left
|
* configured for the device. If the SPI bus is being shared, then it
|
||||||
* in an incompatible state.
|
* may have been left in an incompatible state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
QSPI_SETMODE(qspi, CONFIG_MX25RXX_QSPIMODE);
|
QSPI_SETMODE(qspi, CONFIG_MX25RXX_QSPIMODE);
|
||||||
QSPI_SETBITS(qspi, 8);
|
QSPI_SETBITS(qspi, 8);
|
||||||
QSPI_SETFREQUENCY(qspi,
|
QSPI_SETFREQUENCY(qspi,
|
||||||
read ? CONFIG_MX25RXX_QSPI_READ_FREQUENCY : CONFIG_MX25RXX_QSPI_FREQUENCY);
|
read ? CONFIG_MX25RXX_QSPI_READ_FREQUENCY :
|
||||||
|
CONFIG_MX25RXX_QSPI_FREQUENCY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mx25rxx_unlock(FAR struct qspi_dev_s *qspi)
|
void mx25rxx_unlock(FAR struct qspi_dev_s *qspi)
|
||||||
@@ -538,7 +542,8 @@ int mx25rxx_read_configuration(FAR struct mx25rxx_dev_s *dev)
|
|||||||
return mx25rxx_command_read(dev->qspi, MX25R_RDCR, dev->cmdbuf, 4);
|
return mx25rxx_command_read(dev->qspi, MX25R_RDCR, dev->cmdbuf, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mx25rxx_write_status_config(FAR struct mx25rxx_dev_s *dev, uint8_t status,
|
void mx25rxx_write_status_config(FAR struct mx25rxx_dev_s *dev,
|
||||||
|
uint8_t status,
|
||||||
uint16_t config)
|
uint16_t config)
|
||||||
{
|
{
|
||||||
mx25rxx_write_enable(dev, true);
|
mx25rxx_write_enable(dev, true);
|
||||||
@@ -555,7 +560,9 @@ void mx25rxx_write_status_config(FAR struct mx25rxx_dev_s *dev, uint8_t status,
|
|||||||
mx25rxx_write_enable(dev, false);
|
mx25rxx_write_enable(dev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mx25rxx_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
int mx25rxx_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct mx25rxx_dev_s *priv = (FAR struct mx25rxx_dev_s *)dev;
|
FAR struct mx25rxx_dev_s *priv = (FAR struct mx25rxx_dev_s *)dev;
|
||||||
size_t blocksleft = nblocks;
|
size_t blocksleft = nblocks;
|
||||||
@@ -636,7 +643,9 @@ ssize_t mx25rxx_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
|
|
||||||
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||||
|
|
||||||
/* On this device, we can handle the block read just like the byte-oriented read */
|
/* On this device, we can handle the block read just like the
|
||||||
|
* byte-oriented read
|
||||||
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_MX25RXX_SECTOR512
|
#ifdef CONFIG_MX25RXX_SECTOR512
|
||||||
nbytes = mx25rxx_read(dev, startblock << MX25RXX_SECTOR512_SHIFT,
|
nbytes = mx25rxx_read(dev, startblock << MX25RXX_SECTOR512_SHIFT,
|
||||||
@@ -730,20 +739,22 @@ int mx25rxx_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* array of fixed size blocks. That is most likely not true,
|
||||||
* appear so.
|
* but the client will expect the device logic to do whatever
|
||||||
|
* is necessary to make it appear so.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_MX25RXX_SECTOR512
|
#ifdef CONFIG_MX25RXX_SECTOR512
|
||||||
geo->blocksize = (1 << MX25RXX_SECTOR512_SHIFT);
|
geo->blocksize = (1 << MX25RXX_SECTOR512_SHIFT);
|
||||||
geo->erasesize = (1 << MX25RXX_SECTOR512_SHIFT);
|
geo->erasesize = (1 << MX25RXX_SECTOR512_SHIFT);
|
||||||
geo->neraseblocks = priv->nsectors <<
|
geo->neraseblocks = priv->nsectors <<
|
||||||
(priv->sectorshift - MX25RXX_SECTOR512_SHIFT);
|
(priv->sectorshift -
|
||||||
|
MX25RXX_SECTOR512_SHIFT);
|
||||||
#else
|
#else
|
||||||
geo->blocksize = (1 << priv->pageshift);
|
geo->blocksize = (1 << priv->pageshift);
|
||||||
geo->erasesize = (1 << priv->sectorshift);
|
geo->erasesize = (1 << priv->sectorshift);
|
||||||
@@ -823,18 +834,18 @@ int mx25rxx_readid(struct mx25rxx_dev_s *dev)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mx25rxx_flush_cache
|
* Name: mx25rxx_flush_cache
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MX25RXX_SECTOR512
|
#ifdef CONFIG_MX25RXX_SECTOR512
|
||||||
static int mx25rxx_flush_cache(struct mx25rxx_dev_s *priv)
|
static int mx25rxx_flush_cache(struct mx25rxx_dev_s *priv)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
|
|
||||||
/* If the cache is dirty (meaning that it no longer matches the old FLASH contents)
|
/* If the cache is dirty (meaning that it no longer matches the old FLASH
|
||||||
* or was erased (with the cache containing the correct FLASH contents), then write
|
* contents) or was erased (with the cache containing the correct FLASH
|
||||||
* the cached erase block to FLASH.
|
* contents), then write the cached erase block to FLASH.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (IS_DIRTY(priv) || IS_ERASED(priv))
|
if (IS_DIRTY(priv) || IS_ERASED(priv))
|
||||||
@@ -847,7 +858,10 @@ static int mx25rxx_flush_cache(struct mx25rxx_dev_s *priv)
|
|||||||
|
|
||||||
/* Write entire erase block to FLASH */
|
/* Write entire erase block to FLASH */
|
||||||
|
|
||||||
ret = mx25rxx_write_page(priv, priv->sector, address, 1 << priv->sectorshift);
|
ret = mx25rxx_write_page(priv,
|
||||||
|
priv->sector,
|
||||||
|
address,
|
||||||
|
1 << priv->sectorshift);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
ferr("ERROR: mx25rxx_write_page failed: %d\n", ret);
|
ferr("ERROR: mx25rxx_write_page failed: %d\n", ret);
|
||||||
@@ -863,21 +877,23 @@ static int mx25rxx_flush_cache(struct mx25rxx_dev_s *priv)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mx25rxx_read_cache
|
* Name: mx25rxx_read_cache
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MX25RXX_SECTOR512
|
#ifdef CONFIG_MX25RXX_SECTOR512
|
||||||
static FAR uint8_t *mx25rxx_read_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
static FAR uint8_t *mx25rxx_read_cache(struct mx25rxx_dev_s *priv,
|
||||||
|
off_t sector)
|
||||||
{
|
{
|
||||||
off_t esectno;
|
off_t esectno;
|
||||||
int shift;
|
int shift;
|
||||||
int index;
|
int index;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* Convert from the 512 byte sector to the erase sector size of the device. For
|
/* Convert from the 512 byte sector to the erase sector size of the device.
|
||||||
* example, if the actual erase sector size is 4Kb (1 << 12), then we first
|
* For example, if the actual erase sector size is 4Kb (1 << 12), then we
|
||||||
* shift to the right by 3 to get the sector number in 4096 increments.
|
* first shift to the right by 3 to get the sector number in 4096
|
||||||
|
* increments.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
shift = priv->sectorshift - MX25RXX_SECTOR512_SHIFT;
|
shift = priv->sectorshift - MX25RXX_SECTOR512_SHIFT;
|
||||||
@@ -918,7 +934,9 @@ static FAR uint8_t *mx25rxx_read_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
|||||||
CLR_ERASED(priv); /* The underlying FLASH has not been erased */
|
CLR_ERASED(priv); /* The underlying FLASH has not been erased */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the index to the 512 sector in the erase block that holds the argument */
|
/* Get the index to the 512 sector in the erase block that holds the
|
||||||
|
* argument
|
||||||
|
*/
|
||||||
|
|
||||||
index = sector & ((1 << shift) - 1);
|
index = sector & ((1 << shift) - 1);
|
||||||
|
|
||||||
@@ -928,17 +946,17 @@ static FAR uint8_t *mx25rxx_read_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mx25rxx_erase_cache
|
* Name: mx25rxx_erase_cache
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MX25RXX_SECTOR512
|
#ifdef CONFIG_MX25RXX_SECTOR512
|
||||||
static void mx25rxx_erase_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
static void mx25rxx_erase_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
||||||
{
|
{
|
||||||
FAR uint8_t *dest;
|
FAR uint8_t *dest;
|
||||||
|
|
||||||
/* First, make sure that the erase block containing the 512 byte sector is in
|
/* First, make sure that the erase block containing the 512 byte sector is
|
||||||
* the cache.
|
* in the cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dest = mx25rxx_read_cache(priv, sector);
|
dest = mx25rxx_read_cache(priv, sector);
|
||||||
@@ -950,7 +968,8 @@ static void mx25rxx_erase_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
|||||||
|
|
||||||
if (!IS_ERASED(priv))
|
if (!IS_ERASED(priv))
|
||||||
{
|
{
|
||||||
off_t esectno = sector >> (priv->sectorshift - MX25RXX_SECTOR512_SHIFT);
|
off_t esectno = sector >>
|
||||||
|
(priv->sectorshift - MX25RXX_SECTOR512_SHIFT);
|
||||||
finfo("sector: %jd esectno: %jd\n",
|
finfo("sector: %jd esectno: %jd\n",
|
||||||
(intmax_t)sector, (intmax_t)esectno);
|
(intmax_t)sector, (intmax_t)esectno);
|
||||||
|
|
||||||
@@ -958,9 +977,9 @@ static void mx25rxx_erase_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
|||||||
SET_ERASED(priv);
|
SET_ERASED(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put the cached sector data into the erase state and mark the cache as dirty
|
/* Put the cached sector data into the erase state and mark the cache as
|
||||||
* (but don't update the FLASH yet. The caller will do that at a more optimal
|
* dirty (but don't update the FLASH yet. The caller will do that at a
|
||||||
* time).
|
* more optimal time).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
memset(dest, MX25RXX_ERASED_STATE, MX25RXX_SECTOR512_SIZE);
|
memset(dest, MX25RXX_ERASED_STATE, MX25RXX_SECTOR512_SIZE);
|
||||||
@@ -968,9 +987,9 @@ static void mx25rxx_erase_cache(struct mx25rxx_dev_s *priv, off_t sector)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mx25rxx_write_cache
|
* Name: mx25rxx_write_cache
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_MX25RXX_SECTOR512
|
#ifdef CONFIG_MX25RXX_SECTOR512
|
||||||
static int mx25rxx_write_cache(FAR struct mx25rxx_dev_s *priv,
|
static int mx25rxx_write_cache(FAR struct mx25rxx_dev_s *priv,
|
||||||
@@ -982,20 +1001,21 @@ static int mx25rxx_write_cache(FAR struct mx25rxx_dev_s *priv,
|
|||||||
|
|
||||||
for (; nsectors > 0; nsectors--)
|
for (; nsectors > 0; nsectors--)
|
||||||
{
|
{
|
||||||
/* First, make sure that the erase block containing 512 byte sector is in
|
/* First, make sure that the erase block containing 512 byte sector is
|
||||||
* memory.
|
* in memory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dest = mx25rxx_read_cache(priv, sector);
|
dest = mx25rxx_read_cache(priv, sector);
|
||||||
|
|
||||||
/* Erase the block containing this sector if it is not already erased.
|
/* Erase the block containing this sector if it is not already erased.
|
||||||
* The erased indicated will be cleared when the data from the erase sector
|
* The erased indicated will be cleared when the data from the erase
|
||||||
* is read into the cache and set here when we erase the sector.
|
* sector is read into the cache and set here when we erase the sector.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!IS_ERASED(priv))
|
if (!IS_ERASED(priv))
|
||||||
{
|
{
|
||||||
off_t esectno = sector >> (priv->sectorshift - MX25RXX_SECTOR512_SHIFT);
|
off_t esectno = sector >>
|
||||||
|
(priv->sectorshift - MX25RXX_SECTOR512_SHIFT);
|
||||||
finfo("sector: %jd esectno: %jd\n",
|
finfo("sector: %jd esectno: %jd\n",
|
||||||
(intmax_t)sector, (intmax_t)esectno);
|
(intmax_t)sector, (intmax_t)esectno);
|
||||||
|
|
||||||
@@ -1030,11 +1050,11 @@ static int mx25rxx_write_cache(FAR struct mx25rxx_dev_s *priv,
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
#endif /* CONFIG_MX25RXX_SECTOR512 */
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: mx25rxx_initialize
|
* Name: mx25rxx_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
@@ -1044,9 +1064,10 @@ static int mx25rxx_write_cache(FAR struct mx25rxx_dev_s *priv,
|
|||||||
* instances that can be bound to other functions (such as a block or
|
* instances that can be bound to other functions (such as a block or
|
||||||
* character driver front end).
|
* character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *mx25rxx_initialize(FAR struct qspi_dev_s *qspi, bool unprotect)
|
FAR struct mtd_dev_s *mx25rxx_initialize(FAR struct qspi_dev_s *qspi,
|
||||||
|
bool unprotect)
|
||||||
{
|
{
|
||||||
FAR struct mx25rxx_dev_s *dev;
|
FAR struct mx25rxx_dev_s *dev;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -1058,8 +1079,9 @@ FAR struct mtd_dev_s *mx25rxx_initialize(FAR struct qspi_dev_s *qspi, bool unpro
|
|||||||
/* Allocate a state structure (we allocate the structure instead of using
|
/* Allocate a state structure (we allocate the structure instead of using
|
||||||
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
||||||
* The current implementation would handle only one FLASH part per QuadSPI
|
* The current implementation would handle only one FLASH part per QuadSPI
|
||||||
* device (only because of the QSPIDEV_FLASH(0) definition) and so would have
|
* device (only because of the QSPIDEV_FLASH(0) definition) and so would
|
||||||
* to be extended to handle multiple FLASH parts on the same QuadSPI bus.
|
* have to be extended to handle multiple FLASH parts on the same QuadSPI
|
||||||
|
* bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dev = (FAR struct mx25rxx_dev_s *)kmm_zalloc(sizeof(*dev));
|
dev = (FAR struct mx25rxx_dev_s *)kmm_zalloc(sizeof(*dev));
|
||||||
@@ -1104,7 +1126,9 @@ FAR struct mtd_dev_s *mx25rxx_initialize(FAR struct qspi_dev_s *qspi, bool unpro
|
|||||||
dev->sector = (FAR uint8_t *)QSPI_ALLOC(qspi, 1 << dev->sectorshift);
|
dev->sector = (FAR uint8_t *)QSPI_ALLOC(qspi, 1 << dev->sectorshift);
|
||||||
if (dev->sector == NULL)
|
if (dev->sector == NULL)
|
||||||
{
|
{
|
||||||
/* Allocation failed! Discard all of that work we just did and return NULL */
|
/* Allocation failed! Discard all of that work we just did and
|
||||||
|
* return NULL
|
||||||
|
*/
|
||||||
|
|
||||||
ferr("ERROR: Sector allocation failed\n");
|
ferr("ERROR: Sector allocation failed\n");
|
||||||
goto exit_free_cmdbuf;
|
goto exit_free_cmdbuf;
|
||||||
|
|||||||
+167
-125
File diff suppressed because it is too large
Load Diff
+239
-178
File diff suppressed because it is too large
Load Diff
+26
-11
@@ -53,6 +53,7 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Configuration ************************************************************/
|
/* Configuration ************************************************************/
|
||||||
|
|
||||||
#ifndef CONFIG_RAMMTD_BLOCKSIZE
|
#ifndef CONFIG_RAMMTD_BLOCKSIZE
|
||||||
@@ -117,18 +118,29 @@ static void *ram_write(FAR void *dest, FAR const void *src, size_t len);
|
|||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int ram_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
static int ram_erase(FAR struct mtd_dev_s *dev,
|
||||||
static ssize_t ram_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
|
off_t startblock,
|
||||||
|
size_t nblocks);
|
||||||
|
static ssize_t ram_bread(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
FAR uint8_t *buf);
|
FAR uint8_t *buf);
|
||||||
static ssize_t ram_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
|
static ssize_t ram_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
FAR const uint8_t *buf);
|
FAR const uint8_t *buf);
|
||||||
static ssize_t ram_byteread(FAR struct mtd_dev_s *dev, off_t offset,
|
static ssize_t ram_byteread(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
size_t nbytes, FAR uint8_t *buf);
|
size_t nbytes, FAR uint8_t *buf);
|
||||||
#ifdef CONFIG_MTD_BYTE_WRITE
|
#ifdef CONFIG_MTD_BYTE_WRITE
|
||||||
static ssize_t ram_bytewrite(FAR struct mtd_dev_s *dev, off_t offset,
|
static ssize_t ram_bytewrite(FAR struct mtd_dev_s *dev,
|
||||||
size_t nbytes, FAR const uint8_t *buf);
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
|
FAR const uint8_t *buf);
|
||||||
#endif
|
#endif
|
||||||
static int ram_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int ram_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
@@ -232,7 +244,9 @@ static int ram_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
* Name: ram_bread
|
* Name: ram_bread
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t ram_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
|
static ssize_t ram_bread(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t startblock,
|
||||||
|
size_t nblocks,
|
||||||
FAR uint8_t *buf)
|
FAR uint8_t *buf)
|
||||||
{
|
{
|
||||||
FAR struct ram_dev_s *priv = (FAR struct ram_dev_s *)dev;
|
FAR struct ram_dev_s *priv = (FAR struct ram_dev_s *)dev;
|
||||||
@@ -371,11 +385,12 @@ static int ram_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
{
|
{
|
||||||
case MTDIOC_GEOMETRY:
|
case MTDIOC_GEOMETRY:
|
||||||
{
|
{
|
||||||
FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg);
|
FAR struct mtd_geometry_s *geo =
|
||||||
|
(FAR struct mtd_geometry_s *)((uintptr_t)arg);
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = CONFIG_RAMMTD_BLOCKSIZE;
|
geo->blocksize = CONFIG_RAMMTD_BLOCKSIZE;
|
||||||
|
|||||||
+163
-109
File diff suppressed because it is too large
Load Diff
+249
-169
File diff suppressed because it is too large
Load Diff
+95
-73
@@ -1,7 +1,7 @@
|
|||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* drivers/mtd/sector512.c
|
* drivers/mtd/sector512.c
|
||||||
* MTD driver that contains another MTD driver and converts a larger sector size
|
* MTD driver that contains another MTD driver and converts a larger sector
|
||||||
* to a standard 512 byte sector size.
|
* size to a standard 512 byte sector size.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
@@ -33,11 +33,11 @@
|
|||||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Included Files
|
* Included Files
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
@@ -57,9 +57,9 @@
|
|||||||
#include <nuttx/fs/ioctl.h>
|
#include <nuttx/fs/ioctl.h>
|
||||||
#include <nuttx/mtd/mtd.h>
|
#include <nuttx/mtd/mtd.h>
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Configuration */
|
/* Configuration */
|
||||||
|
|
||||||
@@ -91,13 +91,13 @@
|
|||||||
#define CLR_DIRTY(p) do { (p)->flags &= ~SST25_CACHE_DIRTY; } while (0)
|
#define CLR_DIRTY(p) do { (p)->flags &= ~SST25_CACHE_DIRTY; } while (0)
|
||||||
#define CLR_ERASED(p) do { (p)->flags &= ~SST25_CACHE_DIRTY; } while (0)
|
#define CLR_ERASED(p) do { (p)->flags &= ~SST25_CACHE_DIRTY; } while (0)
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Types
|
* Private Types
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This type represents the state of the MTD device. The struct mtd_dev_s must
|
/* This type represents the state of the MTD device. The struct mtd_dev_s
|
||||||
* appear at the beginning of the definition so that you can freely cast between
|
* must appear at the beginning of the definition so that you can freely
|
||||||
* pointers to struct mtd_dev_s and struct s512_dev_s.
|
* cast between pointers to struct mtd_dev_s and struct s512_dev_s.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct s512_dev_s
|
struct s512_dev_s
|
||||||
@@ -113,9 +113,9 @@ struct s512_dev_s
|
|||||||
FAR uint8_t *eblock; /* Allocated erase block */
|
FAR uint8_t *eblock; /* Allocated erase block */
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
|
|
||||||
@@ -126,26 +126,36 @@ static void s512_cacheflush(struct s512_dev_s *priv);
|
|||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int s512_erase(FAR struct mtd_dev_s *dev, off_t sector512, size_t nsectors);
|
static int s512_erase(FAR struct mtd_dev_s *dev,
|
||||||
static ssize_t s512_bread(FAR struct mtd_dev_s *dev, off_t sector512,
|
off_t sector512,
|
||||||
size_t nsectors, FAR uint8_t *buf);
|
size_t nsectors);
|
||||||
static ssize_t s512_bwrite(FAR struct mtd_dev_s *dev, off_t sector512,
|
static ssize_t s512_bread(FAR struct mtd_dev_s *dev,
|
||||||
size_t nsectors, FAR const uint8_t *buf);
|
off_t sector512,
|
||||||
static ssize_t s512_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
size_t nsectors,
|
||||||
|
FAR uint8_t *buf);
|
||||||
|
static ssize_t s512_bwrite(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t sector512,
|
||||||
|
size_t nsectors,
|
||||||
|
FAR const uint8_t *buf);
|
||||||
|
static ssize_t s512_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
static int s512_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int s512_ioctl(FAR struct mtd_dev_s *dev,
|
||||||
|
int cmd,
|
||||||
|
unsigned long arg);
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_cacheread
|
* Name: s512_cacheread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static FAR uint8_t *s512_cacheread(struct s512_dev_s *priv, off_t sector512)
|
static FAR uint8_t *s512_cacheread(struct s512_dev_s *priv, off_t sector512)
|
||||||
{
|
{
|
||||||
@@ -191,7 +201,9 @@ static FAR uint8_t *s512_cacheread(struct s512_dev_s *priv, off_t sector512)
|
|||||||
CLR_ERASED(priv); /* The underlying FLASH has not been erased */
|
CLR_ERASED(priv); /* The underlying FLASH has not been erased */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the index to the 512 sector in the erase block that holds the argument */
|
/* Get the index to the 512 sector in the erase block that holds the
|
||||||
|
* argument
|
||||||
|
*/
|
||||||
|
|
||||||
index = sector512 % priv->stdperblock;
|
index = sector512 % priv->stdperblock;
|
||||||
|
|
||||||
@@ -200,9 +212,9 @@ static FAR uint8_t *s512_cacheread(struct s512_dev_s *priv, off_t sector512)
|
|||||||
return &priv->eblock[index << SHIFT_512];
|
return &priv->eblock[index << SHIFT_512];
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_cacheflush
|
* Name: s512_cacheflush
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if !defined(CONFIG_MTD_SECT512_READONLY)
|
#if !defined(CONFIG_MTD_SECT512_READONLY)
|
||||||
static void s512_cacheflush(struct s512_dev_s *priv)
|
static void s512_cacheflush(struct s512_dev_s *priv)
|
||||||
@@ -239,11 +251,13 @@ static void s512_cacheflush(struct s512_dev_s *priv)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_erase
|
* Name: s512_erase
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int s512_erase(FAR struct mtd_dev_s *dev, off_t sector512, size_t nsectors)
|
static int s512_erase(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t sector512,
|
||||||
|
size_t nsectors)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MTD_SECT512_READONLY
|
#ifdef CONFIG_MTD_SECT512_READONLY
|
||||||
return -EACESS
|
return -EACESS
|
||||||
@@ -258,21 +272,22 @@ static int s512_erase(FAR struct mtd_dev_s *dev, off_t sector512, size_t nsector
|
|||||||
|
|
||||||
while (sectorsleft-- > 0)
|
while (sectorsleft-- > 0)
|
||||||
{
|
{
|
||||||
/* Erase each sector. First, make sure that the erase block containing the
|
/* Erase each sector. First, make sure that the erase block containing
|
||||||
* 512 byte sector is in the cache.
|
* the 512 byte sector is in the cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dest = s512_cacheread(priv, sector512);
|
dest = s512_cacheread(priv, sector512);
|
||||||
if (!dest)
|
if (!dest)
|
||||||
{
|
{
|
||||||
ferr("ERROR: s512_cacheread(%lu) failed\n", (unsigned long)sector512);
|
ferr("ERROR: s512_cacheread(%lu) failed\n",
|
||||||
|
(unsigned long)sector512);
|
||||||
DEBUGPANIC();
|
DEBUGPANIC();
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Erase the block containing this sector if it is not already erased.
|
/* Erase the block containing this sector if it is not already erased.
|
||||||
* The erased indicator will be cleared when the data from the erase sector
|
* The erased indicator will be cleared when the data from the erase
|
||||||
* is read into the cache and set here when we erase the block.
|
* sector is read into the cache and set here when we erase the block.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!IS_ERASED(priv))
|
if (!IS_ERASED(priv))
|
||||||
@@ -310,9 +325,9 @@ static int s512_erase(FAR struct mtd_dev_s *dev, off_t sector512, size_t nsector
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_bread
|
* Name: s512_bread
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t s512_bread(FAR struct mtd_dev_s *dev, off_t sector512,
|
static ssize_t s512_bread(FAR struct mtd_dev_s *dev, off_t sector512,
|
||||||
size_t nsectors, FAR uint8_t *buffer)
|
size_t nsectors, FAR uint8_t *buffer)
|
||||||
@@ -333,7 +348,8 @@ static ssize_t s512_bread(FAR struct mtd_dev_s *dev, off_t sector512,
|
|||||||
src = s512_cacheread(priv, sector512);
|
src = s512_cacheread(priv, sector512);
|
||||||
if (!src)
|
if (!src)
|
||||||
{
|
{
|
||||||
ferr("ERROR: s512_cacheread(%lu) failed\n", (unsigned long)sector512);
|
ferr("ERROR: s512_cacheread(%lu) failed\n",
|
||||||
|
(unsigned long)sector512);
|
||||||
DEBUGPANIC();
|
DEBUGPANIC();
|
||||||
|
|
||||||
result = (ssize_t)nsectors - remaining;
|
result = (ssize_t)nsectors - remaining;
|
||||||
@@ -345,7 +361,9 @@ static ssize_t s512_bread(FAR struct mtd_dev_s *dev, off_t sector512,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy the sector data from the erase block cache into the user buffer */
|
/* Copy the sector data from the erase block cache into the user
|
||||||
|
* buffer
|
||||||
|
*/
|
||||||
|
|
||||||
memcpy(buffer, src, SECTOR_512);
|
memcpy(buffer, src, SECTOR_512);
|
||||||
|
|
||||||
@@ -356,9 +374,9 @@ static ssize_t s512_bread(FAR struct mtd_dev_s *dev, off_t sector512,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_bwrite
|
* Name: s512_bwrite
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t s512_bwrite(FAR struct mtd_dev_s *dev, off_t sector512,
|
static ssize_t s512_bwrite(FAR struct mtd_dev_s *dev, off_t sector512,
|
||||||
size_t nsectors,
|
size_t nsectors,
|
||||||
@@ -378,8 +396,8 @@ static ssize_t s512_bwrite(FAR struct mtd_dev_s *dev, off_t sector512,
|
|||||||
|
|
||||||
for (remaining = nsectors; remaining > 0; remaining--)
|
for (remaining = nsectors; remaining > 0; remaining--)
|
||||||
{
|
{
|
||||||
/* First, make sure that the erase block containing 512 byte sector is in
|
/* First, make sure that the erase block containing 512 byte sector is
|
||||||
* memory.
|
* in memory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dest = s512_cacheread(priv, sector512);
|
dest = s512_cacheread(priv, sector512);
|
||||||
@@ -395,8 +413,8 @@ static ssize_t s512_bwrite(FAR struct mtd_dev_s *dev, off_t sector512,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Erase the block containing this sector if it is not already erased.
|
/* Erase the block containing this sector if it is not already erased.
|
||||||
* The erased indicated will be cleared when the data from the erase sector
|
* The erased indicated will be cleared when the data from the erase
|
||||||
* is read into the cache and set here when we erase the sector.
|
* sector is read into the cache and set here when we erase the sector.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!IS_ERASED(priv))
|
if (!IS_ERASED(priv))
|
||||||
@@ -434,11 +452,13 @@ static ssize_t s512_bwrite(FAR struct mtd_dev_s *dev, off_t sector512,
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_read
|
* Name: s512_read
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static ssize_t s512_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t s512_read(FAR struct mtd_dev_s *dev,
|
||||||
|
off_t offset,
|
||||||
|
size_t nbytes,
|
||||||
FAR uint8_t *buffer)
|
FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct s512_dev_s *priv = (FAR struct s512_dev_s *)dev;
|
FAR struct s512_dev_s *priv = (FAR struct s512_dev_s *)dev;
|
||||||
@@ -495,9 +515,9 @@ static ssize_t s512_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
|||||||
return nbytes;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_ioctl
|
* Name: s512_ioctl
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static int s512_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
static int s512_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
@@ -514,13 +534,14 @@ static int s512_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
((uintptr_t)arg);
|
((uintptr_t)arg);
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* array of fixed size blocks. That is most likely not true,
|
||||||
* appear so.
|
* but the client will expect the device logic to do whatever
|
||||||
|
* is necessary to make it appear so.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = SECTOR_512;
|
geo->blocksize = SECTOR_512;
|
||||||
@@ -559,23 +580,23 @@ static int s512_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/************************************************************************************
|
/****************************************************************************
|
||||||
* Name: s512_initialize
|
* Name: s512_initialize
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Create an initialized MTD device instance. This MTD driver contains another
|
* Create an initialized MTD device instance. This MTD driver contains
|
||||||
* MTD driver and converts a larger sector size to a standard 512 byte sector
|
* another MTD driver and converts a larger sector size to a standard 512
|
||||||
* size.
|
* byte sector size.
|
||||||
*
|
*
|
||||||
* MTD devices are not registered in the file system, but are created as instances
|
* MTD devices are not registered in the file system, but are created as
|
||||||
* that can be bound to other functions (such as a block or character driver front
|
* instances that can be bound to other functions (such as a block or
|
||||||
* end).
|
* character driver front end).
|
||||||
*
|
*
|
||||||
************************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *s512_initialize(FAR struct mtd_dev_s *mtd)
|
FAR struct mtd_dev_s *s512_initialize(FAR struct mtd_dev_s *mtd)
|
||||||
{
|
{
|
||||||
@@ -595,7 +616,8 @@ FAR struct mtd_dev_s *s512_initialize(FAR struct mtd_dev_s *mtd)
|
|||||||
if (ret < 0 || geo.erasesize <= SECTOR_512 ||
|
if (ret < 0 || geo.erasesize <= SECTOR_512 ||
|
||||||
(geo.erasesize & ~MASK_512) != geo.erasesize)
|
(geo.erasesize & ~MASK_512) != geo.erasesize)
|
||||||
{
|
{
|
||||||
ferr("ERROR: MTDIOC_GEOMETRY ioctl returned %d, eraseize=%" PRId32 "\n",
|
ferr(
|
||||||
|
"ERROR: MTDIOC_GEOMETRY ioctl returned %d, eraseize=%" PRId32 "\n",
|
||||||
ret, geo.erasesize);
|
ret, geo.erasesize);
|
||||||
DEBUGPANIC();
|
DEBUGPANIC();
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -604,8 +626,8 @@ FAR struct mtd_dev_s *s512_initialize(FAR struct mtd_dev_s *mtd)
|
|||||||
/* Allocate a state structure (we allocate the structure instead of using
|
/* Allocate a state structure (we allocate the structure instead of using
|
||||||
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
* a fixed, static allocation so that we can handle multiple FLASH devices.
|
||||||
* The current implementation would handle only one FLASH part per SPI
|
* The current implementation would handle only one FLASH part per SPI
|
||||||
* device (only because of the SPIDEV_FLASH(0) definition) and so would have
|
* device (only because of the SPIDEV_FLASH(0) definition) and so would
|
||||||
* to be extended to handle multiple FLASH parts on the same SPI bus.
|
* have to be extended to handle multiple FLASH parts on the same SPI bus.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
priv = (FAR struct s512_dev_s *)kmm_zalloc(sizeof(struct s512_dev_s));
|
priv = (FAR struct s512_dev_s *)kmm_zalloc(sizeof(struct s512_dev_s));
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ static int skel_ioctl(FAR struct mtd_dev_s *dev, int cmd,
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/* This structure holds the state of the MTD driver */
|
/* This structure holds the state of the MTD driver */
|
||||||
|
|
||||||
static struct skel_dev_s g_skeldev =
|
static struct skel_dev_s g_skeldev =
|
||||||
@@ -255,13 +256,14 @@ static int skel_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)arg;
|
FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)arg;
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information needed to know
|
/* Populate the geometry structure with information needed to
|
||||||
* the capacity and how to access the device.
|
* know the capacity and how to access the device.
|
||||||
*
|
*
|
||||||
* NOTE: that the device is treated as though it where just an array
|
* NOTE:
|
||||||
* of fixed size blocks. That is most likely not true, but the client
|
* that the device is treated as though it where just an array
|
||||||
* will expect the device logic to do whatever is necessary to make it
|
* of fixed size blocks. That is most likely not true, but the
|
||||||
* appear so.
|
* client will expect the device logic to do whatever is
|
||||||
|
* necessary to make it appear so.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
geo->blocksize = 512; /* Size of one read/write block */
|
geo->blocksize = 512; /* Size of one read/write block */
|
||||||
|
|||||||
+216
-151
File diff suppressed because it is too large
Load Diff
+134
-101
File diff suppressed because it is too large
Load Diff
+205
-151
File diff suppressed because it is too large
Load Diff
+248
-178
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user