RAMTRON: Add support for splitting block writes in chunks. Some Re-RAMs like MB85AS4MT has a write buffer size limitation.
This commit is contained in:
parent
9fc5f44ef6
commit
79ee0a5209
@ -3,7 +3,7 @@
|
|||||||
* Driver for SPI-based RAMTRON NVRAM Devices FM25V10 and others (not tested)
|
* Driver for SPI-based RAMTRON NVRAM Devices FM25V10 and others (not tested)
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Uros Platise. All rights reserved.
|
* Copyright (C) 2011 Uros Platise. All rights reserved.
|
||||||
* Copyright (C) 2009-2010, 2012-2013 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2009-2010, 2012-2013, 2017 Gregory Nutt. All rights reserved.
|
||||||
* Author: Uros Platise <uros.platise@isotel.eu>
|
* Author: Uros Platise <uros.platise@isotel.eu>
|
||||||
* Gregory Nutt <gnutt@nuttx.org>
|
* Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
@ -75,6 +75,10 @@
|
|||||||
* Pre-processor Definitions
|
* Pre-processor Definitions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
# define RAMTRON_WRITE_BUFFER_SIZE 256
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Used to abort the write wait */
|
/* Used to abort the write wait */
|
||||||
|
|
||||||
#ifndef CONFIG_MTD_RAMTRON_WRITEWAIT_COUNT
|
#ifndef CONFIG_MTD_RAMTRON_WRITEWAIT_COUNT
|
||||||
@ -153,6 +157,7 @@ struct ramtron_dev_s
|
|||||||
uint16_t nsectors;
|
uint16_t nsectors;
|
||||||
uint32_t npages;
|
uint32_t npages;
|
||||||
uint32_t speed; /* Overridable via ioctl */
|
uint32_t speed; /* Overridable via ioctl */
|
||||||
|
uint32_t wbsiz; /* Write Buffer Size */
|
||||||
FAR const struct ramtron_parts_s *part; /* Part instance */
|
FAR const struct ramtron_parts_s *part; /* Part instance */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -272,6 +277,14 @@ static const struct ramtron_parts_s g_ramtron_parts[] =
|
|||||||
3, /* addr_len */
|
3, /* addr_len */
|
||||||
25000000 /* speed */
|
25000000 /* speed */
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"MB85AS4MT", /* name */
|
||||||
|
0xc9, /* id1 */
|
||||||
|
0x03, /* id2 */
|
||||||
|
512L*1024L, /* size */
|
||||||
|
3, /* addr_len */
|
||||||
|
RAMTRON_INIT_CLK_MAX /* speed */
|
||||||
|
},
|
||||||
#ifdef CONFIG_RAMTRON_FRAM_NON_JEDEC
|
#ifdef CONFIG_RAMTRON_FRAM_NON_JEDEC
|
||||||
{
|
{
|
||||||
"FM25H20", /* name */
|
"FM25H20", /* name */
|
||||||
@ -304,15 +317,21 @@ static inline int ramtron_readid(struct ramtron_dev_s *priv);
|
|||||||
static int ramtron_waitwritecomplete(struct ramtron_dev_s *priv);
|
static int ramtron_waitwritecomplete(struct ramtron_dev_s *priv);
|
||||||
static void ramtron_writeenable(struct ramtron_dev_s *priv);
|
static void ramtron_writeenable(struct ramtron_dev_s *priv);
|
||||||
static inline int ramtron_pagewrite(struct ramtron_dev_s *priv,
|
static inline int ramtron_pagewrite(struct ramtron_dev_s *priv,
|
||||||
FAR const uint8_t *buffer, off_t offset);
|
FAR const uint8_t *buffer, off_t offset,
|
||||||
|
size_t pagesize);
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int ramtron_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
static int ramtron_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
||||||
static ssize_t ramtron_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t ramtron_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf);
|
size_t nblocks, FAR uint8_t *buf);
|
||||||
|
#ifndef RAMTRON_WRITE_BUFFER_SIZE
|
||||||
static ssize_t ramtron_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t ramtron_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);
|
||||||
|
#else
|
||||||
|
static ssize_t ramtron_bwrite_wbsiz(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
|
size_t nblocks, FAR const uint8_t *buf);
|
||||||
|
#endif
|
||||||
static ssize_t ramtron_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t ramtron_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
static int ramtron_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int ramtron_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
||||||
@ -434,6 +453,11 @@ static inline int ramtron_readid(struct ramtron_dev_s *priv)
|
|||||||
priv->pageshift = RAMTRON_EMULATE_PAGE_SHIFT;
|
priv->pageshift = RAMTRON_EMULATE_PAGE_SHIFT;
|
||||||
priv->npages = priv->part->size / (1 << RAMTRON_EMULATE_PAGE_SHIFT);
|
priv->npages = priv->part->size / (1 << RAMTRON_EMULATE_PAGE_SHIFT);
|
||||||
priv->speed = priv->part->speed;
|
priv->speed = priv->part->speed;
|
||||||
|
#ifndef RAMTRON_WRITE_BUFFER_SIZE
|
||||||
|
priv->wbsiz = 1 << priv->pageshift;
|
||||||
|
#else
|
||||||
|
priv->wbsiz = RAMTRON_WRITE_BUFFER_SIZE;
|
||||||
|
#endif
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -533,9 +557,10 @@ static inline void ramtron_sendaddr(const struct ramtron_dev_s *priv, uint32_t a
|
|||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static inline int ramtron_pagewrite(struct ramtron_dev_s *priv,
|
static inline int ramtron_pagewrite(struct ramtron_dev_s *priv,
|
||||||
FAR const uint8_t *buffer, off_t page)
|
FAR const uint8_t *buffer, off_t page,
|
||||||
|
size_t pagesize)
|
||||||
{
|
{
|
||||||
off_t offset = page << priv->pageshift;
|
off_t offset = page * pagesize;
|
||||||
|
|
||||||
finfo("page: %08lx offset: %08lx\n", (long)page, (long)offset);
|
finfo("page: %08lx offset: %08lx\n", (long)page, (long)offset);
|
||||||
|
|
||||||
@ -567,7 +592,7 @@ static inline int ramtron_pagewrite(struct ramtron_dev_s *priv,
|
|||||||
|
|
||||||
/* Then write the specified number of bytes */
|
/* Then write the specified number of bytes */
|
||||||
|
|
||||||
SPI_SNDBLOCK(priv->dev, buffer, 1 << priv->pageshift);
|
SPI_SNDBLOCK(priv->dev, buffer, pagesize);
|
||||||
|
|
||||||
/* Deselect the FLASH: Chip Select high */
|
/* Deselect the FLASH: Chip Select high */
|
||||||
|
|
||||||
@ -624,6 +649,7 @@ static ssize_t ramtron_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
* Name: ramtron_bwrite
|
* Name: ramtron_bwrite
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
|
#ifndef RAMTRON_WRITE_BUFFER_SIZE
|
||||||
static ssize_t ramtron_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t ramtron_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)
|
||||||
{
|
{
|
||||||
@ -637,7 +663,7 @@ static ssize_t ramtron_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
ramtron_lock(priv);
|
ramtron_lock(priv);
|
||||||
while (blocksleft-- > 0)
|
while (blocksleft-- > 0)
|
||||||
{
|
{
|
||||||
if (ramtron_pagewrite(priv, buffer, startblock))
|
if (ramtron_pagewrite(priv, buffer, startblock, 1 << priv->pageshift))
|
||||||
{
|
{
|
||||||
nblocks = 0;
|
nblocks = 0;
|
||||||
break;
|
break;
|
||||||
@ -648,6 +674,51 @@ static ssize_t ramtron_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
|||||||
ramtron_unlock(priv->dev);
|
ramtron_unlock(priv->dev);
|
||||||
return nblocks;
|
return nblocks;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: ramtron_bwrite_wbsiz
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
#ifdef RAMTRON_WRITE_BUFFER_SIZE
|
||||||
|
static ssize_t ramtron_bwrite_wbsiz(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
|
size_t nblocks, FAR const uint8_t *buffer)
|
||||||
|
{
|
||||||
|
FAR struct ramtron_dev_s *priv = (FAR struct ramtron_dev_s *)dev;
|
||||||
|
size_t blocksleft = nblocks;
|
||||||
|
uint32_t p, writesplits;
|
||||||
|
off_t newstartblock;
|
||||||
|
|
||||||
|
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||||
|
|
||||||
|
writesplits = (1 << priv->pageshift) / priv->wbsiz;
|
||||||
|
newstartblock = startblock * writesplits;
|
||||||
|
|
||||||
|
/* Lock the SPI bus and write each page to FLASH */
|
||||||
|
|
||||||
|
ramtron_lock(priv);
|
||||||
|
while (blocksleft-- > 0)
|
||||||
|
{
|
||||||
|
/* Split writes in wbsiz chunks */
|
||||||
|
|
||||||
|
for (p = 0; p < writesplits; p++)
|
||||||
|
{
|
||||||
|
if (ramtron_pagewrite(priv, buffer + p * priv->wbsiz, newstartblock,
|
||||||
|
priv->wbsiz))
|
||||||
|
{
|
||||||
|
nblocks = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
newstartblock++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
ramtron_unlock(priv->dev);
|
||||||
|
return nblocks;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: ramtron_read
|
* Name: ramtron_read
|
||||||
@ -823,7 +894,11 @@ FAR struct mtd_dev_s *ramtron_initialize(FAR struct spi_dev_s *dev)
|
|||||||
|
|
||||||
priv->mtd.erase = ramtron_erase;
|
priv->mtd.erase = ramtron_erase;
|
||||||
priv->mtd.bread = ramtron_bread;
|
priv->mtd.bread = ramtron_bread;
|
||||||
|
#ifndef RAMTRON_WRITE_BUFFER_SIZE
|
||||||
priv->mtd.bwrite = ramtron_bwrite;
|
priv->mtd.bwrite = ramtron_bwrite;
|
||||||
|
#else
|
||||||
|
priv->mtd.bwrite = ramtron_bwrite_wbsiz;
|
||||||
|
#endif
|
||||||
priv->mtd.read = ramtron_read;
|
priv->mtd.read = ramtron_read;
|
||||||
priv->mtd.ioctl = ramtron_ioctl;
|
priv->mtd.ioctl = ramtron_ioctl;
|
||||||
priv->dev = dev;
|
priv->dev = dev;
|
||||||
|
Loading…
Reference in New Issue
Block a user