summaryrefslogtreecommitdiff
path: root/nuttx/drivers/mtd
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-06-26 23:23:08 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-06-26 23:23:08 +0000
commitd07a361adc938b7c8f671d91da4300b8c4a5df7a (patch)
treea2c3486d08ad0151151c359d33e7ee6b128d6e37 /nuttx/drivers/mtd
parenteedcd72b631ebeb471ae60e5368f230d4bce2eb8 (diff)
downloadpx4-nuttx-d07a361adc938b7c8f671d91da4300b8c4a5df7a.tar.gz
px4-nuttx-d07a361adc938b7c8f671d91da4300b8c4a5df7a.tar.bz2
px4-nuttx-d07a361adc938b7c8f671d91da4300b8c4a5df7a.zip
Add logic to un-protect blocks to the SST25 driver
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4873 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/drivers/mtd')
-rw-r--r--nuttx/drivers/mtd/sst25.c168
1 files changed, 144 insertions, 24 deletions
diff --git a/nuttx/drivers/mtd/sst25.c b/nuttx/drivers/mtd/sst25.c
index 53eb02e46..81b5dc1bf 100644
--- a/nuttx/drivers/mtd/sst25.c
+++ b/nuttx/drivers/mtd/sst25.c
@@ -186,7 +186,7 @@ struct sst25_dev_s
uint16_t nsectors; /* Number of erase sectors */
uint8_t sectorshift; /* Log2 of erase sector size */
-#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
+#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
uint8_t flags; /* Buffered sector flags */
uint16_t esectno; /* Erase sector number in the cache*/
FAR uint8_t *sector; /* Allocated sector data */
@@ -202,6 +202,9 @@ struct sst25_dev_s
static void sst25_lock(FAR struct spi_dev_s *dev);
static inline void sst25_unlock(FAR struct spi_dev_s *dev);
static inline int sst25_readid(FAR struct sst25_dev_s *priv);
+#ifndef CONFIG_SST25_READONLY
+static void sst25_unprotect(FAR struct spi_dev_s *dev);
+#endif
static void sst25_waitwritecomplete(FAR struct sst25_dev_s *priv);
static inline void sst25_wren(FAR struct sst25_dev_s *priv);
static inline void sst25_wrdi(FAR struct sst25_dev_s *priv);
@@ -209,8 +212,14 @@ static void sst25_sectorerase(FAR struct sst25_dev_s *priv, off_t offset);
static inline int sst25_chiperase(FAR struct sst25_dev_s *priv);
static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
off_t address, size_t nbytes);
+#ifndef CONFIG_SST25_READONLY
+#ifdef CONFIG_SST25_SLOWWRITE
+static void sst32_bytewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
+ off_t address, size_t nbytes);
+#else
static void sst32_wordwrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
- off_t address, size_t nwords);
+ off_t address, size_t nbytes);
+#endif
#ifdef CONFIG_SST25_SECTOR512
static void sst25_cacheflush(struct sst25_dev_s *priv);
static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector);
@@ -218,6 +227,7 @@ static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector);
static void sst32_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t sector, size_t nsectors);
#endif
+#endif
/* MTD driver methods */
@@ -328,6 +338,38 @@ static inline int sst25_readid(struct sst25_dev_s *priv)
}
/************************************************************************************
+ * Name: sst25_unprotect
+ ************************************************************************************/
+
+#ifndef CONFIG_SST25_READONLY
+static void sst25_unprotect(FAR struct spi_dev_s *dev)
+{
+ /* Select this FLASH part */
+
+ SPI_SELECT(dev, SPIDEV_FLASH, true);
+
+ /* Send "Write enable status (EWSR)" */
+
+ SPI_SEND(dev, SST25_EWSR);
+
+ /* Re-select this FLASH part (This might not be necessary... but is it shown in
+ * the timing diagrams)
+ */
+
+ SPI_SELECT(dev, SPIDEV_FLASH, false);
+ SPI_SELECT(dev, SPIDEV_FLASH, true);
+
+ /* Send "Write enable status (EWSR)" */
+
+ SPI_SEND(dev, SST25_WRSR);
+
+ /* Following by the new status value */
+
+ SPI_SEND(dev, 0);
+}
+#endif
+
+/************************************************************************************
* Name: sst25_waitwritecomplete
************************************************************************************/
@@ -416,7 +458,6 @@ static inline void sst25_wren(struct sst25_dev_s *priv)
/* Deselect the FLASH */
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
- fvdbg("Enabled\n");
}
/************************************************************************************
@@ -476,7 +517,6 @@ static void sst25_sectorerase(struct sst25_dev_s *priv, off_t sector)
/* Deselect the FLASH */
SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
- fvdbg("Erased\n");
}
/************************************************************************************
@@ -529,7 +569,11 @@ static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
/* Send "Read from Memory " instruction */
+#ifdef CONFIG_SST25_SLOWREAD
+ (void)SPI_SEND(priv->dev, SST25_READ);
+#else
(void)SPI_SEND(priv->dev, SST25_FAST_READ);
+#endif
/* Send the address high byte first. */
@@ -539,7 +583,9 @@ static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
/* Send a dummy byte */
+#ifndef CONFIG_SST25_SLOWREAD
(void)SPI_SEND(priv->dev, SST25_DUMMY);
+#endif
/* Then read all of the requested bytes */
@@ -551,12 +597,65 @@ static void sst25_byteread(FAR struct sst25_dev_s *priv, FAR uint8_t *buffer,
}
/************************************************************************************
+ * Name: sst32_bytewrite
+ ************************************************************************************/
+
+#if defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
+static void sst32_bytewrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
+ off_t address, size_t nbytes)
+{
+ fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nbytes);
+ DEBUGASSERT(priv && buffer);
+
+ /* Write each byte individually */
+
+ for (; nbytes > 0; nbytes--)
+ {
+ /* Wait for any preceding write or erase operation to complete. */
+
+ sst25_waitwritecomplete(priv);
+
+ /* Enable write access to the FLASH */
+
+ sst25_wren(priv);
+
+ /* Select this FLASH part */
+
+ SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
+
+ /* Send "Byte Program (BP)" command */
+
+ (void)SPI_SEND(priv->dev, SST25_BP);
+
+ /* Send the byte address high byte first. */
+
+ (void)SPI_SEND(priv->dev, (address >> 16) & 0xff);
+ (void)SPI_SEND(priv->dev, (address >> 8) & 0xff);
+ (void)SPI_SEND(priv->dev, address & 0xff);
+
+ /* Then write the single byte */
+
+ (void)SPI_SEND(priv->dev, *buffer);
+
+ /* Deselect the FLASH and setup for the next pass through the loop */
+
+ SPI_SELECT(priv->dev, SPIDEV_FLASH, false);
+ buffer++;
+ address++;
+ }
+}
+#endif
+
+/************************************************************************************
* Name: sst32_wordwrite
************************************************************************************/
+#if !defined(CONFIG_SST25_SLOWWRITE) && !defined(CONFIG_SST25_READONLY)
static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
- off_t address, size_t nwords)
+ off_t address, size_t nbytes)
{
+ size_t nwords = (nbytes + 1) >> 1;
+
fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nwords);
DEBUGASSERT(priv && buffer);
@@ -564,7 +663,7 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
sst25_waitwritecomplete(priv);
- /* Enable the write access to the FLASH */
+ /* Enable write access to the FLASH */
sst25_wren(priv);
@@ -576,7 +675,7 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
(void)SPI_SEND(priv->dev, SST25_AAI);
- /* Send the page address high byte first. */
+ /* Send the word address high byte first. */
(void)SPI_SEND(priv->dev, (address >> 16) & 0xff);
(void)SPI_SEND(priv->dev, (address >> 8) & 0xff);
@@ -597,14 +696,14 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
for (nwords--; nwords > 0; nwords--)
{
- /* Select this FLASH part */
-
- SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
-
/* Wait for the preceding write to complete. */
sst25_waitwritecomplete(priv);
+ /* Select this FLASH part */
+
+ SPI_SELECT(priv->dev, SPIDEV_FLASH, true);
+
/* Send "Auto Address Increment (AAI)" command with no address */
(void)SPI_SEND(priv->dev, SST25_AAI);
@@ -622,14 +721,14 @@ static void sst32_wordwrite(struct sst25_dev_s *priv, FAR const uint8_t *buffer,
/* Disable writing */
sst25_wrdi(priv);
- fvdbg("Written\n");
}
+#endif
/************************************************************************************
* Name: sst25_cacheflush
************************************************************************************/
-#ifdef CONFIG_SST25_SECTOR512
+#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static void sst25_cacheflush(struct sst25_dev_s *priv)
{
/* If the cached is dirty (meaning that it no longer matches the old FLASH contents)
@@ -641,8 +740,13 @@ static void sst25_cacheflush(struct sst25_dev_s *priv)
{
/* Write entire erase block to FLASH */
+#ifdef CONFIG_SST25_SLOWWRITE
+ sst32_bytewrite(priv, priv->sector, (off_t)priv->esectno << priv->sectorshift,
+ (1 << priv->sectorshift));
+#else
sst32_wordwrite(priv, priv->sector, (off_t)priv->esectno << priv->sectorshift,
- (1 << (priv->sectorshift - 1)));
+ (1 << priv->sectorshift));
+#endif
/* The case is no long dirty and the FLASH is no longer erased */
@@ -656,7 +760,7 @@ static void sst25_cacheflush(struct sst25_dev_s *priv)
* Name: sst25_cacheread
************************************************************************************/
-#ifdef CONFIG_SST25_SECTOR512
+#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector)
{
off_t esectno;
@@ -707,7 +811,7 @@ static FAR uint8_t *sst25_cacheread(struct sst25_dev_s *priv, off_t sector)
* Name: sst25_cacheerase
************************************************************************************/
-#ifdef CONFIG_SST25_SECTOR512
+#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector)
{
FAR uint8_t *dest;
@@ -746,7 +850,7 @@ static void sst25_cacheerase(struct sst25_dev_s *priv, off_t sector)
* Name: sst25_cachewrite
************************************************************************************/
-#ifdef CONFIG_SST25_SECTOR512
+#if defined(CONFIG_SST25_SECTOR512) && !defined(CONFIG_SST25_READONLY)
static void sst32_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *buffer,
off_t sector, size_t nsectors)
{
@@ -797,6 +901,9 @@ static void sst32_cachewrite(FAR struct sst25_dev_s *priv, FAR const uint8_t *bu
static int sst25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
{
+#ifdef CONFIG_SST25_READONLY
+ return -EACESS
+#else
FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev;
size_t blocksleft = nblocks;
@@ -826,6 +933,7 @@ static int sst25_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nbloc
sst25_unlock(priv->dev);
return (int)nblocks;
+#endif
}
/************************************************************************************
@@ -874,6 +982,9 @@ static ssize_t sst25_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t n
static ssize_t sst25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
FAR const uint8_t *buffer)
{
+#ifdef CONFIG_SST25_READONLY
+ return -EACCESS;
+#else
FAR struct sst25_dev_s *priv = (FAR struct sst25_dev_s *)dev;
fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
@@ -881,17 +992,20 @@ static ssize_t sst25_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t
/* Lock the SPI bus and write all of the pages to FLASH */
sst25_lock(priv->dev);
-#ifdef CONFIG_SST25_SECTOR512
+
+#if defined(CONFIG_SST25_SECTOR512)
sst32_cachewrite(priv, buffer, startblock, nblocks);
+#elif defined(CONFIG_SST25_SLOWWRITE)
+ sst32_bytewrite(priv, buffer, startblock << priv->sectorshift,
+ nblocks << priv->sectorshift);
#else
- {
- size_t nwords = (nblocks << (priv->sectorshift - 1));
- sst32_wordwrite(priv, buffer, startblock << priv->sectorshift, nwords);
- }
+ sst32_wordwrite(priv, buffer, startblock << priv->sectorshift,
+ nblocks << priv->sectorshift);
#endif
sst25_unlock(priv->dev);
return nblocks;
+#endif
}
/************************************************************************************
@@ -1034,9 +1148,15 @@ FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev)
kfree(priv);
priv = NULL;
}
-#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
else
{
+ /* Make sure the the FLASH is unprotected so that we can write into it */
+
+#ifndef CONFIG_SST25_READONLY
+ sst25_unprotect(priv->dev);
+#endif
+
+#ifdef CONFIG_SST25_SECTOR512 /* Simulate a 512 byte sector */
/* Allocate a buffer for the erase block cache */
priv->sector = (FAR uint8_t *)kmalloc(1 << priv->sectorshift);
@@ -1048,8 +1168,8 @@ FAR struct mtd_dev_s *sst25_initialize(FAR struct spi_dev_s *dev)
kfree(priv);
priv = NULL;
}
- }
#endif
+ }
}
/* Return the implementation-specific state structure as the MTD device */