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:
Boris Astardzhiev 2017-08-04 08:12:59 -06:00 committed by Gregory Nutt
parent 9fc5f44ef6
commit 79ee0a5209

View File

@ -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;