add support for more is25 mtd devices
This commit is contained in:
parent
5e878186c7
commit
af6c990498
@ -31,6 +31,7 @@
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/signal.h>
|
||||
@ -77,6 +78,7 @@
|
||||
#define IS25_IS25LP064_NSECTORS 2048
|
||||
#define IS25_IS25LP064_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */
|
||||
#define IS25_IS25LP064_NPAGES 32768
|
||||
#define IS25_IS25LP064_ADDRLEN 3
|
||||
|
||||
/* IS25LP128 capacity is 16,777,216 bytes:
|
||||
* (4,096 sectors) * (4,096 bytes per sector)
|
||||
@ -88,30 +90,60 @@
|
||||
#define IS25_IS25LP128_NSECTORS 4096
|
||||
#define IS25_IS25LP128_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */
|
||||
#define IS25_IS25LP128_NPAGES 65536
|
||||
#define IS25_IS25LP128_ADDRLEN 3
|
||||
|
||||
/* IS25LP256 capacity is 33,554,432 bytes:
|
||||
* (8,192 sectors) * (4,096 bytes per sector)
|
||||
* (131,072 pages) * (256 bytes per page)
|
||||
*/
|
||||
|
||||
#define IS25_IS25LP256_CAPACITY 0x19
|
||||
#define IS25_IS25LP256_SECTOR_SHIFT 12 /* Sector size 1 << 12 = 4,096 */
|
||||
#define IS25_IS25LP256_NSECTORS 8192
|
||||
#define IS25_IS25LP256_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */
|
||||
#define IS25_IS25LP256_NPAGES 131072
|
||||
#define IS25_IS25LP256_ADDRLEN 4 /* This chip requires long addresses */
|
||||
|
||||
/* IS25LP512 capacity is 67,108,864 bytes:
|
||||
* (16,364 sectors) * (4,096 bytes per sector)
|
||||
* (262,144 pages) * (256 bytes per page)
|
||||
*/
|
||||
|
||||
#define IS25_IS25LP512_CAPACITY 0x1A
|
||||
#define IS25_IS25LP512_SECTOR_SHIFT 12 /* Sector size 1 << 12 = 4,096 */
|
||||
#define IS25_IS25LP512_NSECTORS 16384
|
||||
#define IS25_IS25LP512_PAGE_SHIFT 8 /* Page size 1 << 8 = 256 */
|
||||
#define IS25_IS25LP512_NPAGES 262144
|
||||
#define IS25_IS25LP512_ADDRLEN 4 /* This chip requires long addresses */
|
||||
|
||||
/* Instructions */
|
||||
|
||||
/* Command Value N Description Addr Dummy Data */
|
||||
|
||||
#define IS25_WREN 0x06 /* 1 Write Enable 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_RDSR 0x05 /* 1 Read Status Register 0 0 >=1 */
|
||||
#define IS25_WREN 0x06 /* 1 Write Enable 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_RDSR 0x05 /* 1 Read Status Register 0 0 >=1 */
|
||||
|
||||
/* #define IS25_EWSR 0x50 1 Write enable status 0 0 0 */
|
||||
#define IS25_WRSR 0x01 /* 1 Write Status Register 0 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_PP 0x02 /* 1 Page Program 3 0 1-256 */
|
||||
#define IS25_SE 0x20 /* 1 Sector Erase 3 0 0 */
|
||||
#define IS25_BE32 0x52 /* 2 32K Block Erase 3 0 0 */
|
||||
#define IS25_BE64 0xD8 /* 2 64K Block Erase 3 0 0 */
|
||||
#define IS25_CER 0xC7 /* 1 Chip Erase 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_READ 0x03 /* 1 Read Data Bytes 3 0 >=1 */
|
||||
#define IS25_FAST_READ 0x0b /* 1 Higher speed read 3 1 >=1 */
|
||||
#define IS25_PP 0x02 /* 1 Page Program 3 0 1-256 */
|
||||
#define IS25_SE 0x20 /* 1 Sector Erase 3 0 0 */
|
||||
#define IS25_BE32 0x52 /* 2 32K Block Erase 3 0 0 */
|
||||
#define IS25_BE64 0xD8 /* 2 64K Block Erase 3 0 0 */
|
||||
#define IS25_CER 0xC7 /* 1 Chip Erase 0 0 0 */
|
||||
#define IS25_EN4B 0xB7 /* 1 Enter 4-byte Address Mode 0 0 0 */
|
||||
|
||||
/* NOTE 1: All parts.
|
||||
* NOTE 2: In IS25XP terminology, 0x52 and 0xd8 are block erase and 0x20
|
||||
* is a sector erase. Block erase provides a faster way to erase
|
||||
* multiple 4K sectors at once.
|
||||
* NOTE 3: The larger chips (256/512Mbit) requires more than 24 address bits.
|
||||
* To enable this, the EN4B command changes the address length of all
|
||||
* commands that take a 3-byte address to 4 bytes. For information,
|
||||
* other commands with a fixed 4-byte address are available.
|
||||
*/
|
||||
|
||||
/* Status register bit definitions */
|
||||
@ -149,9 +181,10 @@ struct is25xp_dev_s
|
||||
FAR struct spi_dev_s *dev; /* Saved SPI interface instance */
|
||||
uint8_t sectorshift; /* 12 */
|
||||
uint8_t pageshift; /* 8 */
|
||||
uint16_t nsectors; /* 2,048 or 4,096 */
|
||||
uint32_t npages; /* 32,768 or 65,536 */
|
||||
uint16_t nsectors; /* 2,048 or 4,096 or 8,192 or 16,384 */
|
||||
uint32_t npages; /* 32,768 or 65,536 or 131,072 or 262,144 */
|
||||
uint8_t lastwaswrite; /* Indicates if last operation was write */
|
||||
uint8_t addrlen; /* Address length, 3 or 4 bytes */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -163,6 +196,7 @@ struct is25xp_dev_s
|
||||
static void is25xp_lock(FAR struct spi_dev_s *dev);
|
||||
static inline void is25xp_unlock(FAR struct spi_dev_s *dev);
|
||||
static inline int is25xp_readid(struct is25xp_dev_s *priv);
|
||||
static void is25xp_enable4byteaddr(struct is25xp_dev_s *priv);
|
||||
static void is25xp_waitwritecomplete(struct is25xp_dev_s *priv);
|
||||
static void is25xp_writeenable(struct is25xp_dev_s *priv);
|
||||
static inline void is25xp_sectorerase(struct is25xp_dev_s *priv,
|
||||
@ -283,6 +317,7 @@ static inline int is25xp_readid(struct is25xp_dev_s *priv)
|
||||
priv->nsectors = IS25_IS25LP064_NSECTORS;
|
||||
priv->pageshift = IS25_IS25LP064_PAGE_SHIFT;
|
||||
priv->npages = IS25_IS25LP064_NPAGES;
|
||||
priv->addrlen = IS25_IS25LP064_ADDRLEN;
|
||||
return OK;
|
||||
}
|
||||
else if (capacity == IS25_IS25LP128_CAPACITY)
|
||||
@ -293,6 +328,29 @@ static inline int is25xp_readid(struct is25xp_dev_s *priv)
|
||||
priv->nsectors = IS25_IS25LP128_NSECTORS;
|
||||
priv->pageshift = IS25_IS25LP128_PAGE_SHIFT;
|
||||
priv->npages = IS25_IS25LP128_NPAGES;
|
||||
priv->addrlen = IS25_IS25LP128_ADDRLEN;
|
||||
return OK;
|
||||
}
|
||||
else if (capacity == IS25_IS25LP256_CAPACITY)
|
||||
{
|
||||
/* Save the FLASH geometry */
|
||||
|
||||
priv->sectorshift = IS25_IS25LP256_SECTOR_SHIFT;
|
||||
priv->nsectors = IS25_IS25LP256_NSECTORS;
|
||||
priv->pageshift = IS25_IS25LP256_PAGE_SHIFT;
|
||||
priv->npages = IS25_IS25LP256_NPAGES;
|
||||
priv->addrlen = IS25_IS25LP256_ADDRLEN;
|
||||
return OK;
|
||||
}
|
||||
else if (capacity == IS25_IS25LP512_CAPACITY)
|
||||
{
|
||||
/* Save the FLASH geometry */
|
||||
|
||||
priv->sectorshift = IS25_IS25LP512_SECTOR_SHIFT;
|
||||
priv->nsectors = IS25_IS25LP512_NSECTORS;
|
||||
priv->pageshift = IS25_IS25LP512_PAGE_SHIFT;
|
||||
priv->npages = IS25_IS25LP512_NPAGES;
|
||||
priv->addrlen = IS25_IS25LP512_ADDRLEN;
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
@ -300,6 +358,27 @@ static inline int is25xp_readid(struct is25xp_dev_s *priv)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: is25xp_enable4byteaddr
|
||||
****************************************************************************/
|
||||
|
||||
static void is25xp_enable4byteaddr(struct is25xp_dev_s *priv)
|
||||
{
|
||||
/* Lock the SPI bus, configure the bus, and select this FLASH part. */
|
||||
|
||||
is25xp_lock(priv->dev);
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), true);
|
||||
|
||||
/* Send the "Enter 4-byte Address Mode (EN4B)" command */
|
||||
|
||||
SPI_SEND(priv->dev, IS25_EN4B);
|
||||
|
||||
/* Deselect the FLASH and unlock the bus */
|
||||
|
||||
SPI_SELECT(priv->dev, SPIDEV_FLASH(0), false);
|
||||
is25xp_unlock(priv->dev);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: is25xp_waitwritecomplete
|
||||
****************************************************************************/
|
||||
@ -472,6 +551,11 @@ static void is25xp_sectorerase(struct is25xp_dev_s *priv,
|
||||
* and the values used in the following two bytes don't really matter.
|
||||
*/
|
||||
|
||||
if (priv->addrlen == 4)
|
||||
{
|
||||
SPI_SEND(priv->dev, (offset >> 24) & 0xff);
|
||||
}
|
||||
|
||||
SPI_SEND(priv->dev, (offset >> 16) & 0xff);
|
||||
SPI_SEND(priv->dev, (offset >> 8) & 0xff);
|
||||
SPI_SEND(priv->dev, offset & 0xff);
|
||||
@ -554,6 +638,11 @@ static inline void is25xp_pagewrite(struct is25xp_dev_s *priv,
|
||||
|
||||
/* Send the page offset high byte first. */
|
||||
|
||||
if (priv->addrlen == 4)
|
||||
{
|
||||
SPI_SEND(priv->dev, (offset >> 24) & 0xff);
|
||||
}
|
||||
|
||||
SPI_SEND(priv->dev, (offset >> 16) & 0xff);
|
||||
SPI_SEND(priv->dev, (offset >> 8) & 0xff);
|
||||
SPI_SEND(priv->dev, offset & 0xff);
|
||||
@ -602,6 +691,11 @@ static inline void is25xp_bytewrite(struct is25xp_dev_s *priv,
|
||||
|
||||
/* Send the page offset high byte first. */
|
||||
|
||||
if (priv->addrlen == 4)
|
||||
{
|
||||
SPI_SEND(priv->dev, (offset >> 24) & 0xff);
|
||||
}
|
||||
|
||||
SPI_SEND(priv->dev, (offset >> 16) & 0xff);
|
||||
SPI_SEND(priv->dev, (offset >> 8) & 0xff);
|
||||
SPI_SEND(priv->dev, offset & 0xff);
|
||||
@ -795,6 +889,11 @@ static ssize_t is25xp_read(FAR struct mtd_dev_s *dev,
|
||||
|
||||
/* Send the page offset high byte first. */
|
||||
|
||||
if (priv->addrlen == 4)
|
||||
{
|
||||
SPI_SEND(priv->dev, (offset >> 24) & 0xff);
|
||||
}
|
||||
|
||||
SPI_SEND(priv->dev, (offset >> 16) & 0xff);
|
||||
SPI_SEND(priv->dev, (offset >> 8) & 0xff);
|
||||
SPI_SEND(priv->dev, offset & 0xff);
|
||||
@ -927,8 +1026,9 @@ static int is25xp_ioctl(FAR struct mtd_dev_s *dev,
|
||||
|
||||
ret = OK;
|
||||
|
||||
finfo("blocksize: %d erasesize: %d neraseblocks: %d\n",
|
||||
geo->blocksize, geo->erasesize, geo->neraseblocks);
|
||||
finfo("blocksize: %"PRIu32" erasesize: %"PRIu32
|
||||
" neraseblocks: %"PRIu32"\n", geo->blocksize,
|
||||
geo->erasesize, geo->neraseblocks);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1034,6 +1134,13 @@ FAR struct mtd_dev_s *is25xp_initialize(FAR struct spi_dev_s *dev)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For the large capacity chip, enable 4-byte address mode. */
|
||||
|
||||
if (priv->addrlen == 4)
|
||||
{
|
||||
is25xp_enable4byteaddr(priv);
|
||||
}
|
||||
|
||||
/* Make sure that the FLASH is unprotected so that we can
|
||||
* write into it
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user