ST25FL1: Flesh out more initialization logic
This commit is contained in:
parent
e6be3cea9f
commit
7936819fcc
2
arch
2
arch
@ -1 +1 @@
|
|||||||
Subproject commit 5336c646386607424e3426fb488d73241abb5f08
|
Subproject commit 5f3f8a53bbcc0fd201bed99de4f69a6fa97597eb
|
@ -174,12 +174,20 @@
|
|||||||
|
|
||||||
/* Flash Manufacturer JEDEC IDs */
|
/* Flash Manufacturer JEDEC IDs */
|
||||||
|
|
||||||
|
#define ST25FL1_JEDEC_ID_SPANSION 0x01
|
||||||
#define ST25FL1_JEDEC_ID_ATMEL 0x1f
|
#define ST25FL1_JEDEC_ID_ATMEL 0x1f
|
||||||
#define ST25FL1_JEDEC_ID_ST 0x20
|
#define ST25FL1_JEDEC_ID_ST 0x20
|
||||||
#define ST25FL1_JEDEC_ID_SST 0xbf
|
#define ST25FL1_JEDEC_ID_SST 0xbf
|
||||||
#define ST25FL1_JEDEC_ID_MACRONIX 0xc2
|
#define ST25FL1_JEDEC_ID_MACRONIX 0xc2
|
||||||
#define ST25FL1_JEDEC_ID_WINBOND 0xef
|
#define ST25FL1_JEDEC_ID_WINBOND 0xef
|
||||||
|
|
||||||
|
/* ST25FL1 JEDIC IDs */
|
||||||
|
|
||||||
|
#define ST25FL1_JEDEC_DEVICE_TYPE 0x40 /* ST25FL1 memory devuce type */
|
||||||
|
#define S25FL116K_JEDEC_CAPACITY 0x15 /* S25FL116K memory capacity */
|
||||||
|
#define S25FL132K_JEDEC_CAPACITY 0x16 /* S25FL132K memory capacity */
|
||||||
|
#define S25FL164K_JEDEC_CAPACITY 0x17 /* S25FL164K memory capacity */
|
||||||
|
|
||||||
/* ST25FL1 Registers ****************************************************************/
|
/* ST25FL1 Registers ****************************************************************/
|
||||||
/* Status register bit definitions */
|
/* Status register bit definitions */
|
||||||
|
|
||||||
@ -198,7 +206,7 @@
|
|||||||
# define STATUS1_TB_BOTTOM (1 << 5) /* 1 = BP2-BP0 protect Bottom up */
|
# define STATUS1_TB_BOTTOM (1 << 5) /* 1 = BP2-BP0 protect Bottom up */
|
||||||
#define STATUS1_SEC_MASK (1 << 6) /* Bit 6: Sector / Block Protect */
|
#define STATUS1_SEC_MASK (1 << 6) /* Bit 6: Sector / Block Protect */
|
||||||
# define STATUS1_SEC_BLOCK (0 << 6) /* 0 = BP2-BP0 protect 64-kB blocks */
|
# define STATUS1_SEC_BLOCK (0 << 6) /* 0 = BP2-BP0 protect 64-kB blocks */
|
||||||
# define STATUS1_SEC_BLOCK (1 << 6) /* 1 = BP2-BP0 protect 4-kB sectors */
|
# define STATUS1_SEC_SECTOR (1 << 6) /* 1 = BP2-BP0 protect 4-kB sectors */
|
||||||
#define STATUS1_SRP0_MASK (1 << 7) /* Bit 7: Status register protect 0 */
|
#define STATUS1_SRP0_MASK (1 << 7) /* Bit 7: Status register protect 0 */
|
||||||
# define STATUS1_SRP0_UNLOCKED (0 << 7) /* 0 = WP# no effect / PS Lock Down */
|
# define STATUS1_SRP0_UNLOCKED (0 << 7) /* 0 = WP# no effect / PS Lock Down */
|
||||||
# define STATUS1_SRP0_LOCKED (1 << 7) /* 1 = WP# protect / OTP Lock Down */
|
# define STATUS1_SRP0_LOCKED (1 << 7) /* 1 = WP# protect / OTP Lock Down */
|
||||||
@ -238,12 +246,15 @@
|
|||||||
/* All members of the family support uniform 4K-byte sectors */
|
/* All members of the family support uniform 4K-byte sectors */
|
||||||
|
|
||||||
#define S25FL116K_SECTOR_SIZE (4*1024)
|
#define S25FL116K_SECTOR_SIZE (4*1024)
|
||||||
|
#define S25FL116K_SECTOR_SHIFT (12)
|
||||||
#define S25FL116K_SECTOR_COUNT (512)
|
#define S25FL116K_SECTOR_COUNT (512)
|
||||||
|
|
||||||
#define S25FL132K_SECTOR_SIZE (4*1024)
|
#define S25FL132K_SECTOR_SIZE (4*1024)
|
||||||
|
#define S25FL163K_SECTOR_SHIFT (12)
|
||||||
#define S25FL132K_SECTOR_COUNT (1024)
|
#define S25FL132K_SECTOR_COUNT (1024)
|
||||||
|
|
||||||
#define S25FL164K_SECTOR_SIZE (4*1024)
|
#define S25FL164K_SECTOR_SIZE (4*1024)
|
||||||
|
#define S25FL164K_SECTOR_SHIFT (12)
|
||||||
#define S25FL164K_SECTOR_COUNT (2048)
|
#define S25FL164K_SECTOR_COUNT (2048)
|
||||||
|
|
||||||
/* Cache flags **********************************************************************/
|
/* Cache flags **********************************************************************/
|
||||||
@ -276,8 +287,9 @@
|
|||||||
struct st25fl1_dev_s
|
struct st25fl1_dev_s
|
||||||
{
|
{
|
||||||
struct mtd_dev_s mtd; /* MTD interface */
|
struct mtd_dev_s mtd; /* MTD interface */
|
||||||
FAR struct spi_dev_s *qspi; /* Saved QuadSPI interface instance */
|
FAR struct qspi_dev_s *qspi; /* Saved QuadSPI interface instance */
|
||||||
uint16_t nsectors; /* Number of erase sectors */
|
uint16_t nsectors; /* Number of erase sectors */
|
||||||
|
uint8_t sectorshift; /* Log2 of sector size */
|
||||||
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
uint8_t flags; /* Buffered sector flags */
|
uint8_t flags; /* Buffered sector flags */
|
||||||
@ -290,39 +302,54 @@ struct st25fl1_dev_s
|
|||||||
* Private Function Prototypes
|
* Private Function Prototypes
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
/* Helpers */
|
/* Locking */
|
||||||
|
|
||||||
static void st25fl1_lock(FAR struct spi_dev_s *qspi);
|
static void st25fl1_lock(FAR struct qspi_dev_s *qspi);
|
||||||
static inline void st25fl1_unlock(FAR struct spi_dev_s *qspi);
|
static inline void st25fl1_unlock(FAR struct qspi_dev_s *qspi);
|
||||||
static inline int st25fl1_readid(FAR struct st25fl1_dev_s *priv);
|
|
||||||
|
/* Low-level message helpers */
|
||||||
|
|
||||||
|
static int st25fl1_command(FAR struct qspi_dev_s *qspi, uint8_t cmd);
|
||||||
|
static int st25fl1_command_address(FAR struct qspi_dev_s *qspi, uint8_t cmd,
|
||||||
|
off_t address);
|
||||||
|
static int st25fl1_command_read(FAR struct qspi_dev_s *qspi, uint8_t cmd,
|
||||||
|
FAR void *buffer, size_t buflen);
|
||||||
|
static int st25fl1_command_write(FAR struct qspi_dev_s *qspi, uint8_t cmd,
|
||||||
|
FAR const void *buffer, size_t buflen);
|
||||||
|
static uint8_t sf25fl1_read_status1(FAR struct qspi_dev_s *qspi);
|
||||||
|
static uint8_t sf25fl1_read_status2(FAR struct qspi_dev_s *qspi);
|
||||||
|
static uint8_t sf25fl1_read_status3(FAR struct qspi_dev_s *qspi);
|
||||||
|
static void st25fl1_write_enable(FAR struct qspi_dev_s *qspi);
|
||||||
|
static void st25fl1_write_disable(FAR struct qspi_dev_s *qspi);
|
||||||
|
|
||||||
|
static int st25fl1_readid(FAR struct st25fl1_dev_s *priv);
|
||||||
static void st25fl1_unprotect(FAR struct st25fl1_dev_s *priv);
|
static void st25fl1_unprotect(FAR struct st25fl1_dev_s *priv);
|
||||||
static uint8_t st25fl1_waitwritecomplete(FAR struct st25fl1_dev_s *priv);
|
static uint8_t st25fl1_waitwritecomplete(FAR struct st25fl1_dev_s *priv);
|
||||||
static inline void st25fl1_wren(FAR struct st25fl1_dev_s *priv);
|
static int st25fl1_erase_sector(FAR struct st25fl1_dev_s *priv, off_t offset);
|
||||||
static inline void st25fl1_wrdi(FAR struct st25fl1_dev_s *priv);
|
static int st25fl1_erase_chip(FAR struct st25fl1_dev_s *priv);
|
||||||
static void st25fl1_sectorerase(FAR struct st25fl1_dev_s *priv, off_t offset);
|
static void st25fl1_read_byte(FAR struct st25fl1_dev_s *priv, FAR uint8_t *buffer,
|
||||||
static inline int st25fl1_chiperase(FAR struct st25fl1_dev_s *priv);
|
off_t address, size_t nbytes);
|
||||||
static void st25fl1_byteread(FAR struct st25fl1_dev_s *priv, FAR uint8_t *buffer,
|
static void st25fl1_write_page(FAR struct st25fl1_dev_s *priv,
|
||||||
off_t address, size_t nbytes);
|
FAR const uint8_t *buffer, off_t address, size_t nbytes);
|
||||||
static void st25fl1_pagewrite(FAR struct st25fl1_dev_s *priv, FAR const uint8_t *buffer,
|
|
||||||
off_t address, size_t nbytes);
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
static void st25fl1_cacheflush(struct st25fl1_dev_s *priv);
|
static void st25fl1_flush_cache(struct st25fl1_dev_s *priv);
|
||||||
static FAR uint8_t *st25fl1_cacheread(struct st25fl1_dev_s *priv, off_t sector);
|
static FAR uint8_t *st25fl1_read_cache(struct st25fl1_dev_s *priv, off_t sector);
|
||||||
static void st25fl1_cacheerase(struct st25fl1_dev_s *priv, off_t sector);
|
static void st25fl1_erase_cache(struct st25fl1_dev_s *priv, off_t sector);
|
||||||
static void st25fl1_cachewrite(FAR struct st25fl1_dev_s *priv, FAR const uint8_t *buffer,
|
static void st25fl1_write_cache(FAR struct st25fl1_dev_s *priv,
|
||||||
off_t sector, size_t nsectors);
|
FAR const uint8_t *buffer, off_t sector, size_t nsectors);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* MTD driver methods */
|
/* MTD driver methods */
|
||||||
|
|
||||||
static int st25fl1_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks);
|
static int st25fl1_erase(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
|
size_t nblocks);
|
||||||
static ssize_t st25fl1_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t st25fl1_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
size_t nblocks, FAR uint8_t *buf);
|
size_t nblocks, FAR uint8_t *buf);
|
||||||
static ssize_t st25fl1_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
static ssize_t st25fl1_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);
|
||||||
static ssize_t st25fl1_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
static ssize_t st25fl1_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbytes,
|
||||||
FAR uint8_t *buffer);
|
FAR uint8_t *buffer);
|
||||||
static int st25fl1_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
static int st25fl1_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@ -336,7 +363,7 @@ static int st25fl1_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg);
|
|||||||
* Name: st25fl1_lock
|
* Name: st25fl1_lock
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static void st25fl1_lock(FAR struct spi_dev_s *qspi)
|
static void st25fl1_lock(FAR struct qspi_dev_s *qspi)
|
||||||
{
|
{
|
||||||
/* On QuadSPI busses where there are multiple devices, it will be necessary to
|
/* On QuadSPI busses where there are multiple devices, it will be necessary to
|
||||||
* lock QuadSPI to have exclusive access to the busses for a sequence of
|
* lock QuadSPI to have exclusive access to the busses for a sequence of
|
||||||
@ -363,42 +390,189 @@ static void st25fl1_lock(FAR struct spi_dev_s *qspi)
|
|||||||
* Name: st25fl1_unlock
|
* Name: st25fl1_unlock
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static inline void st25fl1_unlock(FAR struct spi_dev_s *qspi)
|
static inline void st25fl1_unlock(FAR struct qspi_dev_s *qspi)
|
||||||
{
|
{
|
||||||
(void)QSPI_LOCK(qspi, false);
|
(void)QSPI_LOCK(qspi, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: st25fl1_command
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static int st25fl1_command(FAR struct qspi_dev_s *qspi, uint8_t cmd)
|
||||||
|
{
|
||||||
|
/* This function just allows us to insert debug output */
|
||||||
|
|
||||||
|
fvdbg("CMD: %02x\n", cmd);
|
||||||
|
return QSPI_COMMAND(qspi, (uint16_t)cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: st25fl1_command_read
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static int st25fl1_command_read(FAR struct qspi_dev_s *qspi, uint8_t cmd,
|
||||||
|
FAR void *buffer, size_t buflen)
|
||||||
|
{
|
||||||
|
/* This function just allows us to insert debug output */
|
||||||
|
|
||||||
|
fvdbg("CMD: %02x buflen: %lu\n", cmd, (unsigned long)buflen);
|
||||||
|
return QSPI_COMMAND_READ(qspi, (uint16_t)cmd, buffer, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: st25fl1_command_write
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static int st25fl1_command_write(FAR struct qspi_dev_s *qspi, uint8_t cmd,
|
||||||
|
FAR const void *buffer, size_t buflen)
|
||||||
|
{
|
||||||
|
/* This function just allows us to insert debug output */
|
||||||
|
|
||||||
|
fvdbg("CMD: %02x buflen: %lu\n", cmd, (unsigned long)buflen);
|
||||||
|
return QSPI_COMMAND_WRITE(qspi, (uint16_t)cmd, buffer, buflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: sf25fl1_read_status1
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static uint8_t sf25fl1_read_status1(FAR struct qspi_dev_s *qspi)
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
DEBUGVERIFY(st25fl1_command_read(qspi, ST25FL1_READ_STATUS1,
|
||||||
|
(FAR void *)&status, 1));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: sf25fl1_read_status2
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static uint8_t sf25fl1_read_status2(FAR struct qspi_dev_s *qspi)
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
DEBUGVERIFY(st25fl1_command_read(qspi, ST25FL1_READ_STATUS2,
|
||||||
|
(FAR void *)&status, 1));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: sf25fl1_read_status3
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static uint8_t sf25fl1_read_status3(FAR struct qspi_dev_s *qspi)
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
DEBUGVERIFY(st25fl1_command_read(qspi, ST25FL1_READ_STATUS3,
|
||||||
|
(FAR void *)&status, 1));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: st25fl1_write_enable
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static void st25fl1_write_enable(FAR struct qspi_dev_s *qspi)
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
st25fl1_command(qspi, ST25FL1_WRITE_ENABLE);
|
||||||
|
status = sf25fl1_read_status1(qspi);
|
||||||
|
}
|
||||||
|
while ((status & STATUS1_WEL_MASK) != STATUS1_WEL_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: st25fl1_write_disable
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static void st25fl1_write_disable(FAR struct qspi_dev_s *qspi)
|
||||||
|
{
|
||||||
|
uint8_t status;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
st25fl1_command(qspi, ST25FL1_WRITE_DISABLE);
|
||||||
|
status = sf25fl1_read_status1(qspi);
|
||||||
|
}
|
||||||
|
while ((status & STATUS1_WEL_MASK) != STATUS1_WEL_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: st25fl1_write_status
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
static void st25fl1_write_status(FAR struct qspi_dev_s *qspi, uint8_t status[3])
|
||||||
|
{
|
||||||
|
st25fl1_write_enable(qspi);
|
||||||
|
st25fl1_command_write(qspi, ST25FL1_WRITE_STATUS, (FAR const void *)status, 3);
|
||||||
|
st25fl1_write_disable(qspi);
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_readid
|
* Name: st25fl1_readid
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static inline int st25fl1_readid(struct st25fl1_dev_s *priv)
|
static inline int st25fl1_readid(struct st25fl1_dev_s *priv)
|
||||||
{
|
{
|
||||||
uint16_t manufacturer;
|
uint8_t jedecid[3];
|
||||||
uint16_t memory;
|
|
||||||
uint16_t capacity;
|
|
||||||
|
|
||||||
fvdbg("priv: %p\n", priv);
|
|
||||||
|
|
||||||
/* Lock the QuadSPI bus and configure the bus. */
|
/* Lock the QuadSPI bus and configure the bus. */
|
||||||
|
|
||||||
st25fl1_lock(priv->qspi);
|
st25fl1_lock(priv->qspi);
|
||||||
|
|
||||||
#warning Missing Logic
|
/* Read the JEDEC ID */
|
||||||
|
|
||||||
|
st25fl1_command_read(priv->qspi, ST25FL1_JEDEC_ID, jedecid, 3);
|
||||||
|
|
||||||
/* Unlock the bus */
|
/* Unlock the bus */
|
||||||
|
|
||||||
st25fl1_unlock(priv->qspi);
|
st25fl1_unlock(priv->qspi);
|
||||||
|
|
||||||
fvdbg("manufacturer: %02x memory: %02x capacity: %02x\n",
|
fvdbg("Manufacturer: %02x Device Type %02x, Capacity: %02x",
|
||||||
manufacturer, memory, capacity);
|
jedecid[0], jedecid[1], jedecid[2]);
|
||||||
|
|
||||||
/* Check for a valid manufacturer and memory type */
|
/* Check for a recognized memory device type */
|
||||||
#warning Missing Logic
|
|
||||||
|
|
||||||
/* We don't understand the manufacturer or the memory type */
|
if (jedecid[1] != ST25FL1_JEDEC_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: Unrecognized device type: %02x\n", jedecid[1]);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
return -ENODEV;
|
/* Check for a supported capacity */
|
||||||
|
|
||||||
|
switch (jedecid[2])
|
||||||
|
{
|
||||||
|
case S25FL116K_JEDEC_CAPACITY:
|
||||||
|
priv->sectorshift = S25FL116K_SECTOR_SHIFT;
|
||||||
|
priv->nsectors = S25FL116K_SECTOR_COUNT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S25FL132K_JEDEC_CAPACITY:
|
||||||
|
priv->sectorshift = S25FL163K_SECTOR_SHIFT;
|
||||||
|
priv->nsectors = S25FL132K_SECTOR_COUNT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case S25FL164K_JEDEC_CAPACITY:
|
||||||
|
priv->sectorshift = S25FL164K_SECTOR_SHIFT;
|
||||||
|
priv->nsectors = S25FL164K_SECTOR_COUNT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Support for this part is not implemented yet */
|
||||||
|
|
||||||
|
default:
|
||||||
|
fdbg("ERROR: Unsupported memory capacity: %02x\n", jedecid[2]);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -424,54 +598,93 @@ static uint8_t st25fl1_waitwritecomplete(struct st25fl1_dev_s *priv)
|
|||||||
{
|
{
|
||||||
#warning Missing Logic
|
#warning Missing Logic
|
||||||
}
|
}
|
||||||
while ((status & ST25FL1_SR_BUSY) != 0);
|
while ((status & STATUS1_BUSY_MASK) == STATUS1_BUSY);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_wren
|
* Name: st25fl1_erase_sector
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static inline void st25fl1_wren(struct st25fl1_dev_s *priv)
|
static int st25fl1_erase_sector(struct st25fl1_dev_s *priv, off_t sector)
|
||||||
{
|
{
|
||||||
#warning Missing Logic
|
#ifdef CONFIG_DEBUG
|
||||||
|
uint8_t status;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
fvdbg("sector: %08lx\n", (unsigned long)sector);
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG
|
||||||
|
/* Check that the flash is ready and unprotected */
|
||||||
|
|
||||||
|
status = sf25fl1_read_status1(priv->qspi);
|
||||||
|
if ((status & STATUS1_BUSY_MASK) != STATUS1_READY)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: Flash busy: %02x", status);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((status & STATUS1_BP_MASK) != 0)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: Flash protected: %02x", status);
|
||||||
|
/* REVISIT: Should check if this particular sector is protected */
|
||||||
|
//return -EACCES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Send the sector erase command */
|
||||||
|
|
||||||
|
st25fl1_write_enable(priv->qspi);
|
||||||
|
st25fl1_command_address(priv->qspi, ST25FL1_SECTOR_ERASE, sector);
|
||||||
|
|
||||||
|
/* Wait for erasure to finish */
|
||||||
|
|
||||||
|
while ((sf25fl1_read_status1(priv->qspi) & STATUS1_BUSY_MASK) != 0);
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_wrdi
|
* Name: st25fl1_erase_chip
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static inline void st25fl1_wrdi(struct st25fl1_dev_s *priv)
|
static int st25fl1_erase_chip(struct st25fl1_dev_s *priv)
|
||||||
{
|
{
|
||||||
#warning Missing Logic
|
uint8_t status;
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG
|
||||||
|
/* Check if the FLASH is protected */
|
||||||
|
|
||||||
|
status = sf25fl1_read_status1(priv->qspi);
|
||||||
|
if ((status & STATUS1_BP_MASK) != 0)
|
||||||
|
{
|
||||||
|
fdbg("ERROR: FLASH is Protected: %02x", status);
|
||||||
|
return -EACCES;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Erase the whole chip */
|
||||||
|
|
||||||
|
st25fl1_write_enable(priv->qspi);
|
||||||
|
st25fl1_command(priv->qspi, ST25FL1_CHIP_ERASE_2);
|
||||||
|
|
||||||
|
/* Wait for the erasure to complete */
|
||||||
|
|
||||||
|
status = sf25fl1_read_status1(priv->qspi);
|
||||||
|
while ((status & STATUS1_BUSY_MASK) != 0)
|
||||||
|
{
|
||||||
|
usleep(200*1000);
|
||||||
|
status = sf25fl1_read_status1(priv->qspi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_sectorerase
|
* Name: st25fl1_read_byte
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static void st25fl1_sectorerase(struct st25fl1_dev_s *priv, off_t sector)
|
static void st25fl1_read_byte(FAR struct st25fl1_dev_s *priv, FAR uint8_t *buffer,
|
||||||
{
|
|
||||||
fvdbg("sector: %08lx\n", (long)sector);
|
|
||||||
#warning Missing Logic
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* Name: st25fl1_chiperase
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
static inline int st25fl1_chiperase(struct st25fl1_dev_s *priv)
|
|
||||||
{
|
|
||||||
fvdbg("priv: %p\n", priv);
|
|
||||||
#warning Missing Logic
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* Name: st25fl1_byteread
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
static void st25fl1_byteread(FAR struct st25fl1_dev_s *priv, FAR uint8_t *buffer,
|
|
||||||
off_t address, size_t nbytes)
|
off_t address, size_t nbytes)
|
||||||
{
|
{
|
||||||
fvdbg("address: %08lx nbytes: %d\n", (long)address, (int)nbytes);
|
fvdbg("address: %08lx nbytes: %d\n", (long)address, (int)nbytes);
|
||||||
@ -479,10 +692,10 @@ static void st25fl1_byteread(FAR struct st25fl1_dev_s *priv, FAR uint8_t *buffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_pagewrite
|
* Name: st25fl1_write_page
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static void st25fl1_pagewrite(struct st25fl1_dev_s *priv, FAR const uint8_t *buffer,
|
static void st25fl1_write_page(struct st25fl1_dev_s *priv, FAR const uint8_t *buffer,
|
||||||
off_t address, size_t nbytes)
|
off_t address, size_t nbytes)
|
||||||
{
|
{
|
||||||
fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nbytes);
|
fvdbg("address: %08lx nwords: %d\n", (long)address, (int)nbytes);
|
||||||
@ -490,11 +703,11 @@ static void st25fl1_pagewrite(struct st25fl1_dev_s *priv, FAR const uint8_t *buf
|
|||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_cacheflush
|
* Name: st25fl1_flush_cache
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
static void st25fl1_cacheflush(struct st25fl1_dev_s *priv)
|
static void st25fl1_flush_cache(struct st25fl1_dev_s *priv)
|
||||||
{
|
{
|
||||||
/* If the cached is dirty (meaning that it no longer matches the old FLASH contents)
|
/* If the cached is dirty (meaning that it no longer matches the old FLASH contents)
|
||||||
* or was erased (with the cache containing the correct FLASH contents), then write
|
* or was erased (with the cache containing the correct FLASH contents), then write
|
||||||
@ -515,11 +728,11 @@ static void st25fl1_cacheflush(struct st25fl1_dev_s *priv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_cacheread
|
* Name: st25fl1_read_cache
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
static FAR uint8_t *st25fl1_cacheread(struct st25fl1_dev_s *priv, off_t sector)
|
static FAR uint8_t *st25fl1_read_cache(struct st25fl1_dev_s *priv, off_t sector)
|
||||||
{
|
{
|
||||||
off_t esectno;
|
off_t esectno;
|
||||||
int shift;
|
int shift;
|
||||||
@ -530,7 +743,7 @@ static FAR uint8_t *st25fl1_cacheread(struct st25fl1_dev_s *priv, off_t sector)
|
|||||||
* shift to the right by 3 to get the sector number in 4096 increments.
|
* shift to the right by 3 to get the sector number in 4096 increments.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
shift = ST25FL1_SECTOR_SHIFT - ST25FL1_SECTOR512_SHIFT;
|
shift = priv->sectorshift - ST25FL1_SECTOR512_SHIFT;
|
||||||
esectno = sector >> shift;
|
esectno = sector >> shift;
|
||||||
fvdbg("sector: %ld esectno: %d shift=%d\n", sector, esectno, shift);
|
fvdbg("sector: %ld esectno: %d shift=%d\n", sector, esectno, shift);
|
||||||
|
|
||||||
@ -540,11 +753,12 @@ static FAR uint8_t *st25fl1_cacheread(struct st25fl1_dev_s *priv, off_t sector)
|
|||||||
{
|
{
|
||||||
/* No.. Flush any dirty erase block currently in the cache */
|
/* No.. Flush any dirty erase block currently in the cache */
|
||||||
|
|
||||||
st25fl1_cacheflush(priv);
|
st25fl1_flush_cache(priv);
|
||||||
|
|
||||||
/* Read the erase block into the cache */
|
/* Read the erase block into the cache */
|
||||||
|
|
||||||
st25fl1_byteread(priv, priv->sector, (esectno << ST25FL1_SECTOR_SHIFT), ST25FL1_SECTOR_SIZE);
|
st25fl1_read_byte(priv, priv->sector, (esectno << priv->sectorshift)
|
||||||
|
(1 << priv->sectorshift));
|
||||||
|
|
||||||
/* Mark the sector as cached */
|
/* Mark the sector as cached */
|
||||||
|
|
||||||
@ -566,11 +780,11 @@ static FAR uint8_t *st25fl1_cacheread(struct st25fl1_dev_s *priv, off_t sector)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_cacheerase
|
* Name: st25fl1_erase_cache
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
static void st25fl1_cacheerase(struct st25fl1_dev_s *priv, off_t sector)
|
static void st25fl1_erase_cache(struct st25fl1_dev_s *priv, off_t sector)
|
||||||
{
|
{
|
||||||
FAR uint8_t *dest;
|
FAR uint8_t *dest;
|
||||||
|
|
||||||
@ -578,7 +792,7 @@ static void st25fl1_cacheerase(struct st25fl1_dev_s *priv, off_t sector)
|
|||||||
* the cache.
|
* the cache.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dest = st25fl1_cacheread(priv, sector);
|
dest = st25fl1_read_cache(priv, sector);
|
||||||
|
|
||||||
/* Erase the block containing this sector if it is not already erased.
|
/* Erase the block containing this sector if it is not already erased.
|
||||||
* The erased indicated will be cleared when the data from the erase sector
|
* The erased indicated will be cleared when the data from the erase sector
|
||||||
@ -587,10 +801,10 @@ static void st25fl1_cacheerase(struct st25fl1_dev_s *priv, off_t sector)
|
|||||||
|
|
||||||
if (!IS_ERASED(priv))
|
if (!IS_ERASED(priv))
|
||||||
{
|
{
|
||||||
off_t esectno = sector >> (ST25FL1_SECTOR_SHIFT - ST25FL1_SECTOR512_SHIFT);
|
off_t esectno = sector >> (priv->sectorshift - ST25FL1_SECTOR512_SHIFT);
|
||||||
fvdbg("sector: %ld esectno: %d\n", sector, esectno);
|
fvdbg("sector: %ld esectno: %d\n", sector, esectno);
|
||||||
|
|
||||||
st25fl1_sectorerase(priv, esectno);
|
DEBUGVERIFY(st25fl1_erase_sector(priv, esectno));
|
||||||
SET_ERASED(priv);
|
SET_ERASED(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -605,11 +819,11 @@ static void st25fl1_cacheerase(struct st25fl1_dev_s *priv, off_t sector)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_cachewrite
|
* Name: st25fl1_write_cache
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
static void st25fl1_cachewrite(FAR struct st25fl1_dev_s *priv, FAR const uint8_t *buffer,
|
static void st25fl1_write_cache(FAR struct st25fl1_dev_s *priv, FAR const uint8_t *buffer,
|
||||||
off_t sector, size_t nsectors)
|
off_t sector, size_t nsectors)
|
||||||
{
|
{
|
||||||
FAR uint8_t *dest;
|
FAR uint8_t *dest;
|
||||||
@ -620,7 +834,7 @@ static void st25fl1_cachewrite(FAR struct st25fl1_dev_s *priv, FAR const uint8_t
|
|||||||
* memory.
|
* memory.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
dest = st25fl1_cacheread(priv, sector);
|
dest = st25fl1_read_cache(priv, sector);
|
||||||
|
|
||||||
/* Erase the block containing this sector if it is not already erased.
|
/* Erase the block containing this sector if it is not already erased.
|
||||||
* The erased indicated will be cleared when the data from the erase sector
|
* The erased indicated will be cleared when the data from the erase sector
|
||||||
@ -629,10 +843,10 @@ static void st25fl1_cachewrite(FAR struct st25fl1_dev_s *priv, FAR const uint8_t
|
|||||||
|
|
||||||
if (!IS_ERASED(priv))
|
if (!IS_ERASED(priv))
|
||||||
{
|
{
|
||||||
off_t esectno = sector >> (ST25FL1_SECTOR_SHIFT - ST25FL1_SECTOR512_SHIFT);
|
off_t esectno = sector >> (priv->sectorshift - ST25FL1_SECTOR512_SHIFT);
|
||||||
fvdbg("sector: %ld esectno: %d\n", sector, esectno);
|
fvdbg("sector: %ld esectno: %d\n", sector, esectno);
|
||||||
|
|
||||||
st25fl1_sectorerase(priv, esectno);
|
DEBUGVERIFY(st25fl1_erase_sector(priv, esectno));
|
||||||
SET_ERASED(priv);
|
SET_ERASED(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,7 +863,7 @@ static void st25fl1_cachewrite(FAR struct st25fl1_dev_s *priv, FAR const uint8_t
|
|||||||
|
|
||||||
/* Flush the last erase block left in the cache */
|
/* Flush the last erase block left in the cache */
|
||||||
|
|
||||||
st25fl1_cacheflush(priv);
|
st25fl1_flush_cache(priv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -660,19 +874,44 @@ static void st25fl1_cachewrite(FAR struct st25fl1_dev_s *priv, FAR const uint8_t
|
|||||||
static int st25fl1_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
static int st25fl1_erase(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks)
|
||||||
{
|
{
|
||||||
FAR struct st25fl1_dev_s *priv = (FAR struct st25fl1_dev_s *)dev;
|
FAR struct st25fl1_dev_s *priv = (FAR struct st25fl1_dev_s *)dev;
|
||||||
|
size_t blocksleft = nblocks;
|
||||||
|
|
||||||
fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||||
#warning Missing Logic
|
|
||||||
|
|
||||||
|
/* Lock access to the SPI bus until we complete the erase */
|
||||||
|
|
||||||
|
st25fl1_lock(priv->qspi);
|
||||||
|
|
||||||
|
while (blocksleft-- > 0)
|
||||||
|
{
|
||||||
|
/* Erase each sector */
|
||||||
|
|
||||||
|
#ifdef CONFIG_S25FL1_SECTOR512
|
||||||
|
st25fl1_erase_cache(priv, startblock);
|
||||||
|
#else
|
||||||
|
st25fl1_erase_sector(priv, startblock);
|
||||||
|
#endif
|
||||||
|
startblock++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_S25FL1_SECTOR512
|
||||||
|
/* Flush the last erase block left in the cache */
|
||||||
|
|
||||||
|
st25fl1_flush_cache(priv);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
st25fl1_unlock(priv->qspi);
|
||||||
|
return (int)nblocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: st25fl1_bread
|
* Name: st25fl1_bread
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static ssize_t st25fl1_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
|
static ssize_t st25fl1_bread(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
FAR uint8_t *buffer)
|
size_t nblocks, FAR uint8_t *buffer)
|
||||||
{
|
{
|
||||||
|
FAR struct st25fl1_dev_s *priv = (FAR struct st25fl1_dev_s *)dev;
|
||||||
ssize_t nbytes;
|
ssize_t nbytes;
|
||||||
|
|
||||||
fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
fvdbg("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||||
@ -680,16 +919,18 @@ static ssize_t st25fl1_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t
|
|||||||
/* On this device, we can handle the block read just like the byte-oriented read */
|
/* On this device, we can handle the block read just like the byte-oriented read */
|
||||||
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
nbytes = st25fl1_read(dev, startblock << ST25FL1_SECTOR512_SHIFT, nblocks << ST25FL1_SECTOR512_SHIFT, buffer);
|
nbytes = st25fl1_read(dev, startblock << ST25FL1_SECTOR512_SHIFT,
|
||||||
|
nblocks << ST25FL1_SECTOR512_SHIFT, buffer);
|
||||||
if (nbytes > 0)
|
if (nbytes > 0)
|
||||||
{
|
{
|
||||||
nbytes >>= ST25FL1_SECTOR512_SHIFT;
|
nbytes >>= ST25FL1_SECTOR512_SHIFT;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
nbytes = st25fl1_read(dev, startblock << ST25FL1_SECTOR_SHIFT, nblocks << ST25FL1_SECTOR_SHIFT, buffer);
|
nbytes = st25fl1_read(dev, startblock << priv->sectorshift,
|
||||||
|
nblocks << priv->sectorshift, buffer);
|
||||||
if (nbytes > 0)
|
if (nbytes > 0)
|
||||||
{
|
{
|
||||||
nbytes >>= ST25FL1_SECTOR_SHIFT;
|
nbytes >>= priv->sectorshift;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -700,8 +941,8 @@ static ssize_t st25fl1_bread(FAR struct mtd_dev_s *dev, off_t startblock, size_t
|
|||||||
* Name: st25fl1_bwrite
|
* Name: st25fl1_bwrite
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
static ssize_t st25fl1_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_t nblocks,
|
static ssize_t st25fl1_bwrite(FAR struct mtd_dev_s *dev, off_t startblock,
|
||||||
FAR const uint8_t *buffer)
|
size_t nblocks, FAR const uint8_t *buffer)
|
||||||
{
|
{
|
||||||
FAR struct st25fl1_dev_s *priv = (FAR struct st25fl1_dev_s *)dev;
|
FAR struct st25fl1_dev_s *priv = (FAR struct st25fl1_dev_s *)dev;
|
||||||
|
|
||||||
@ -712,10 +953,10 @@ static ssize_t st25fl1_bwrite(FAR struct mtd_dev_s *dev, off_t startblock, size_
|
|||||||
st25fl1_lock(priv->qspi);
|
st25fl1_lock(priv->qspi);
|
||||||
|
|
||||||
#if defined(CONFIG_ST25FL1_SECTOR512)
|
#if defined(CONFIG_ST25FL1_SECTOR512)
|
||||||
st25fl1_cachewrite(priv, buffer, startblock, nblocks);
|
st25fl1_write_cache(priv, buffer, startblock, nblocks);
|
||||||
#else
|
#else
|
||||||
st25fl1_pagewrite(priv, buffer, startblock << ST25FL1_SECTOR_SHIFT,
|
st25fl1_write_page(priv, buffer, startblock << priv->sectorshift,
|
||||||
nblocks << ST25FL1_SECTOR_SHIFT);
|
nblocks << priv->sectorshift);
|
||||||
#endif
|
#endif
|
||||||
st25fl1_unlock(priv->qspi);
|
st25fl1_unlock(priv->qspi);
|
||||||
|
|
||||||
@ -736,7 +977,7 @@ static ssize_t st25fl1_read(FAR struct mtd_dev_s *dev, off_t offset, size_t nbyt
|
|||||||
/* Lock the QuadSPI bus and select this FLASH part */
|
/* Lock the QuadSPI bus and select this FLASH part */
|
||||||
|
|
||||||
st25fl1_lock(priv->qspi);
|
st25fl1_lock(priv->qspi);
|
||||||
st25fl1_byteread(priv, buffer, offset, nbytes);
|
st25fl1_read_byte(priv, buffer, offset, nbytes);
|
||||||
st25fl1_unlock(priv->qspi);
|
st25fl1_unlock(priv->qspi);
|
||||||
|
|
||||||
fvdbg("return nbytes: %d\n", (int)nbytes);
|
fvdbg("return nbytes: %d\n", (int)nbytes);
|
||||||
@ -758,7 +999,9 @@ static int st25fl1_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
{
|
{
|
||||||
case MTDIOC_GEOMETRY:
|
case MTDIOC_GEOMETRY:
|
||||||
{
|
{
|
||||||
FAR struct mtd_geometry_s *geo = (FAR struct mtd_geometry_s *)((uintptr_t)arg);
|
FAR struct mtd_geometry_s *geo =
|
||||||
|
(FAR struct mtd_geometry_s *)((uintptr_t)arg);
|
||||||
|
|
||||||
if (geo)
|
if (geo)
|
||||||
{
|
{
|
||||||
/* Populate the geometry structure with information need to know
|
/* Populate the geometry structure with information need to know
|
||||||
@ -773,10 +1016,10 @@ static int st25fl1_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
#ifdef CONFIG_ST25FL1_SECTOR512
|
#ifdef CONFIG_ST25FL1_SECTOR512
|
||||||
geo->blocksize = (1 << ST25FL1_SECTOR512_SHIFT);
|
geo->blocksize = (1 << ST25FL1_SECTOR512_SHIFT);
|
||||||
geo->erasesize = (1 << ST25FL1_SECTOR512_SHIFT);
|
geo->erasesize = (1 << ST25FL1_SECTOR512_SHIFT);
|
||||||
geo->neraseblocks = priv->nsectors << (ST25FL1_SECTOR_SHIFT - ST25FL1_SECTOR512_SHIFT);
|
geo->neraseblocks = priv->nsectors << (priv->sectorshift - ST25FL1_SECTOR512_SHIFT);
|
||||||
#else
|
#else
|
||||||
geo->blocksize = ST25FL1_SECTOR_SIZE;
|
geo->blocksize = (1 << priv->sectorshift);
|
||||||
geo->erasesize = ST25FL1_SECTOR_SIZE;
|
geo->erasesize = (1 << priv->sectorshift);
|
||||||
geo->neraseblocks = priv->nsectors;
|
geo->neraseblocks = priv->nsectors;
|
||||||
#endif
|
#endif
|
||||||
ret = OK;
|
ret = OK;
|
||||||
@ -789,11 +1032,11 @@ static int st25fl1_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
|
|
||||||
case MTDIOC_BULKERASE:
|
case MTDIOC_BULKERASE:
|
||||||
{
|
{
|
||||||
/* Erase the entire device */
|
/* Erase the entire device */
|
||||||
|
|
||||||
st25fl1_lock(priv->qspi);
|
st25fl1_lock(priv->qspi);
|
||||||
ret = st25fl1_chiperase(priv);
|
ret = st25fl1_erase_chip(priv);
|
||||||
st25fl1_unlock(priv->qspi);
|
st25fl1_unlock(priv->qspi);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -821,9 +1064,10 @@ static int st25fl1_ioctl(FAR struct mtd_dev_s *dev, int cmd, unsigned long arg)
|
|||||||
*
|
*
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
FAR struct mtd_dev_s *st25fl1_initialize(FAR struct spi_dev_s *qspi)
|
FAR struct mtd_dev_s *st25fl1_initialize(FAR struct qspi_dev_s *qspi)
|
||||||
{
|
{
|
||||||
FAR struct st25fl1_dev_s *priv;
|
FAR struct st25fl1_dev_s *priv;
|
||||||
|
uint8_t status[3];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fvdbg("qspi: %p\n", qspi);
|
fvdbg("qspi: %p\n", qspi);
|
||||||
@ -856,30 +1100,42 @@ FAR struct mtd_dev_s *st25fl1_initialize(FAR struct spi_dev_s *qspi)
|
|||||||
{
|
{
|
||||||
/* Unrecognized! Discard all of that work we just did and return NULL */
|
/* Unrecognized! Discard all of that work we just did and return NULL */
|
||||||
|
|
||||||
fdbg("Unrecognized\n");
|
fdbg("ERROR Unrecognized QSPI device\n");
|
||||||
kmm_free(priv);
|
kmm_free(priv);
|
||||||
priv = NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Make sure that the FLASH is unprotected so that we can write into it */
|
|
||||||
|
|
||||||
st25fl1_unprotect(priv);
|
/* Enable quad mode */
|
||||||
|
|
||||||
|
status[0] = sf25fl1_read_status1(priv->qspi);
|
||||||
|
status[1] = sf25fl1_read_status2(priv->qspi);
|
||||||
|
status[2] = sf25fl1_read_status3(priv->qspi);
|
||||||
|
|
||||||
|
while ((status[1] & STATUS2_QUAD_ENABLE_MASK) == 0)
|
||||||
|
{
|
||||||
|
status[1] |= STATUS2_QUAD_ENABLE;
|
||||||
|
st25fl1_write_status(priv->qspi, status);
|
||||||
|
status[1] = sf25fl1_read_status2(priv->qspi);
|
||||||
|
usleep(50*1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure that the FLASH is unprotected so that we can write into it */
|
||||||
|
|
||||||
|
st25fl1_unprotect(priv);
|
||||||
|
|
||||||
#ifdef CONFIG_ST25FL1_SECTOR512 /* Simulate a 512 byte sector */
|
#ifdef CONFIG_ST25FL1_SECTOR512 /* Simulate a 512 byte sector */
|
||||||
/* Allocate a buffer for the erase block cache */
|
/* Allocate a buffer for the erase block cache */
|
||||||
|
|
||||||
priv->sector = (FAR uint8_t *)kmm_malloc(ST25FL1_SECTOR_SIZE);
|
priv->sector = (FAR uint8_t *)kmm_malloc((1 << priv->sectorshift));
|
||||||
if (!priv->sector)
|
if (!priv->sector)
|
||||||
{
|
{
|
||||||
/* Allocation failed! Discard all of that work we just did and return NULL */
|
/* Allocation failed! Discard all of that work we just did and return NULL */
|
||||||
|
|
||||||
fdbg("Allocation failed\n");
|
fdbg("ERROR: Allocation failed\n");
|
||||||
kmm_free(priv);
|
kmm_free(priv);
|
||||||
priv = NULL;
|
return NULL;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MTD_REGISTRATION
|
#ifdef CONFIG_MTD_REGISTRATION
|
||||||
|
Loading…
Reference in New Issue
Block a user