add support for more is25 mtd devices

This commit is contained in:
Sebastien Lorquet 2023-01-05 17:44:30 +01:00 committed by Xiang Xiao
parent 5e878186c7
commit af6c990498
1 changed files with 124 additions and 17 deletions

View File

@ -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
*/