mirror of
https://github.com/apache/nuttx.git
synced 2026-05-23 06:39:01 +08:00
arch/arm64/imx9 4byte addressing to nor
-Use 4byte addressing in flexpi nor -report 4k blocksize to userland -increase clock to 100MHz -some cleanup Signed-off-by: Jouni Ukkonen <jouni.ukkonen@unikie.com>
This commit is contained in:
committed by
Xiang Xiao
parent
d260e7f59e
commit
a3d1b06214
@@ -1235,9 +1235,9 @@ struct flexspi_dev_s *imx9_flexspi_initialize(int intf)
|
||||
|
||||
imx9_ccm_gate_on(CCM_LPCG_FLEXSPI1, true);
|
||||
|
||||
/* Configure clock to safe 50MHz, src clock is 800Mhz */
|
||||
/* Configure clock to safe 100MHz, src clock is 800Mhz */
|
||||
|
||||
imx9_ccm_configure_root_clock(CCM_CR_FLEXSPI1, SYS_PLL1PFD1, 16);
|
||||
imx9_ccm_configure_root_clock(CCM_CR_FLEXSPI1, SYS_PLL1PFD1, 8);
|
||||
|
||||
/* Has the FlexSPI hardware been initialized? */
|
||||
|
||||
|
||||
@@ -246,12 +246,14 @@
|
||||
#define M25P_BE 0xc7 /* 1 Bulk Erase 0 0 0 */
|
||||
#define M25P_DP 0xb9 /* 2 Deep power down 0 0 0 */
|
||||
#define M25P_RES 0xab /* 2 Read Electronic Signature 0 3 >=1 */
|
||||
#define M25P_SSE 0x20 /* 3 Sub-Sector Erase 0 0 0 */
|
||||
#define M25P_SSE 0x21 /* 3 Sub-Sector Erase 4 0 0 */
|
||||
#define M25P_WECR 0x61 /* 1 Write Enhanched config 0 0 1 */
|
||||
#define M25P_RFSR 0x70 /* 1 Read Flag Status Register 0 0 1 */
|
||||
#define M25P_4B_ENTER 0xB7 /* 1 Enter 4byte addressing 0 0 0 */
|
||||
|
||||
/* Quad commands */
|
||||
#define M25P_Q_FAST_RD 0x6b /* 1 Quad output fast read 3/4 0 1-256 */
|
||||
#define M25P_Q_FAST_PP 0x32 /* 1 Quad input fast program 3/4 0 1-256 */
|
||||
#define M25P_Q_FAST_RD 0x6c /* 1 Quad output fast read 4 0 1-256 */
|
||||
#define M25P_Q_FAST_PP 0x34 /* 1 Quad input fast program 4 0 1-256 */
|
||||
#define M25P_Q_ENTER 0x35 /* 1 Enter Quad input/output 0 0 0 */
|
||||
|
||||
/* NOTE 1: All parts.
|
||||
@@ -260,18 +262,23 @@
|
||||
* is a sector erase.
|
||||
*/
|
||||
|
||||
#define ADDRESS_24BIT 0x18
|
||||
#define ADDRESS_32BIT 0x20
|
||||
|
||||
enum
|
||||
{
|
||||
/* SPI instructions */
|
||||
|
||||
READ_ID,
|
||||
READ_STATUS_REG,
|
||||
READ_FLAG_STATUS_REG,
|
||||
WRITE_STATUS_REG,
|
||||
WRITE_ENABLE,
|
||||
ERASE_SECTOR,
|
||||
ERASE_CHIP,
|
||||
ENTER_DDR,
|
||||
READ_FAST,
|
||||
ENTER_4BYTE,
|
||||
|
||||
/* Quad SPI instructions */
|
||||
|
||||
@@ -296,6 +303,12 @@ static const uint32_t g_flexspi_nor_lut[][4] =
|
||||
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04),
|
||||
},
|
||||
|
||||
[READ_FLAG_STATUS_REG] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_RFSR,
|
||||
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04),
|
||||
},
|
||||
|
||||
[WRITE_STATUS_REG] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_WRSR,
|
||||
@@ -311,7 +324,7 @@ static const uint32_t g_flexspi_nor_lut[][4] =
|
||||
[ERASE_SECTOR] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_SSE, /* note: sub-sector erase */
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, ADDRESS_32BIT),
|
||||
},
|
||||
|
||||
[ERASE_CHIP] =
|
||||
@@ -323,7 +336,7 @@ static const uint32_t g_flexspi_nor_lut[][4] =
|
||||
[READ_FAST_QUAD_OUTPUT] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_Q_FAST_RD,
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, ADDRESS_32BIT),
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_DUMMY_SDR, FLEXSPI_4PAD, 0x08,
|
||||
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_4PAD, 0x04),
|
||||
},
|
||||
@@ -331,11 +344,17 @@ static const uint32_t g_flexspi_nor_lut[][4] =
|
||||
[PAGE_PROGRAM_QUAD_INPUT] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_Q_FAST_PP,
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, ADDRESS_32BIT),
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_4PAD, 0x04,
|
||||
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
|
||||
},
|
||||
|
||||
[ENTER_4BYTE] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_4B_ENTER,
|
||||
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
|
||||
},
|
||||
|
||||
[ENTER_QPI] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_Q_ENTER,
|
||||
@@ -351,7 +370,7 @@ static const uint32_t g_flexspi_nor_lut[][4] =
|
||||
[READ_FAST] =
|
||||
{
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_FAST_READ,
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
|
||||
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, ADDRESS_32BIT),
|
||||
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_DUMMY_SDR, FLEXSPI_1PAD, 0x08,
|
||||
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04)
|
||||
},
|
||||
@@ -410,7 +429,7 @@ static int imx9_flexspi_nor_ioctl(struct mtd_dev_s *dev,
|
||||
|
||||
static struct flexspi_device_config_s g_flexspi_device_config =
|
||||
{
|
||||
.flexspi_root_clk = 50000000,
|
||||
.flexspi_root_clk = 100000000,
|
||||
.flash_size = 1024 * 64, /* size in kB */
|
||||
.cs_interval_unit = FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE,
|
||||
.cs_interval = 0,
|
||||
@@ -627,9 +646,9 @@ static int imx9_flexspi_nor_get_id(
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static int imx9_flexspi_nor_read_status(
|
||||
static int imx9_flexspi_nor_read_register(
|
||||
const struct imx9_flexspi_nor_dev_s *dev,
|
||||
uint32_t *status)
|
||||
uint32_t *value, uint32_t len, int seq)
|
||||
{
|
||||
int stat;
|
||||
|
||||
@@ -639,8 +658,8 @@ static int imx9_flexspi_nor_read_status(
|
||||
.port = dev->port,
|
||||
.cmd_type = FLEXSPI_READ,
|
||||
.seq_number = 1,
|
||||
.seq_index = READ_STATUS_REG,
|
||||
.data = status,
|
||||
.seq_index = seq,
|
||||
.data = value,
|
||||
.data_size = 1,
|
||||
};
|
||||
|
||||
@@ -653,34 +672,9 @@ static int imx9_flexspi_nor_read_status(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx9_flexspi_nor_write_status(
|
||||
static int imx9_flexspi_nor_write_cmd(
|
||||
const struct imx9_flexspi_nor_dev_s *dev,
|
||||
uint32_t *status)
|
||||
{
|
||||
int stat;
|
||||
|
||||
struct flexspi_transfer_s transfer =
|
||||
{
|
||||
.device_address = 0,
|
||||
.port = dev->port,
|
||||
.cmd_type = FLEXSPI_WRITE,
|
||||
.seq_number = 1,
|
||||
.seq_index = WRITE_STATUS_REG,
|
||||
.data = status,
|
||||
.data_size = 1,
|
||||
};
|
||||
|
||||
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
|
||||
if (stat != 0)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx9_flexspi_nor_write_enable(
|
||||
const struct imx9_flexspi_nor_dev_s *dev)
|
||||
int cmd)
|
||||
{
|
||||
int stat;
|
||||
|
||||
@@ -690,7 +684,7 @@ static int imx9_flexspi_nor_write_enable(
|
||||
.port = dev->port,
|
||||
.cmd_type = FLEXSPI_COMMAND,
|
||||
.seq_number = 1,
|
||||
.seq_index = WRITE_ENABLE,
|
||||
.seq_index = cmd,
|
||||
.data = NULL,
|
||||
.data_size = 0,
|
||||
};
|
||||
@@ -730,31 +724,6 @@ static int imx9_flexspi_nor_erase_sector(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx9_flexspi_nor_erase_chip(
|
||||
const struct imx9_flexspi_nor_dev_s *dev)
|
||||
{
|
||||
int stat;
|
||||
|
||||
struct flexspi_transfer_s transfer =
|
||||
{
|
||||
.device_address = 0,
|
||||
.port = dev->port,
|
||||
.cmd_type = FLEXSPI_COMMAND,
|
||||
.seq_number = 1,
|
||||
.seq_index = ERASE_CHIP,
|
||||
.data = NULL,
|
||||
.data_size = 0,
|
||||
};
|
||||
|
||||
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
|
||||
if (stat != 0)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx9_flexspi_nor_page_program(
|
||||
const struct imx9_flexspi_nor_dev_s *dev,
|
||||
off_t offset,
|
||||
@@ -793,7 +762,7 @@ static int imx9_flexspi_nor_wait_bus_busy(
|
||||
|
||||
do
|
||||
{
|
||||
ret = imx9_flexspi_nor_read_status(dev, &status);
|
||||
ret = imx9_flexspi_nor_read_register(dev, &status, 1, READ_STATUS_REG);
|
||||
if (ret)
|
||||
{
|
||||
return ret;
|
||||
@@ -804,18 +773,6 @@ static int imx9_flexspi_nor_wait_bus_busy(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx9_flexspi_nor_enable_quad_mode(
|
||||
const struct imx9_flexspi_nor_dev_s *dev)
|
||||
{
|
||||
uint32_t status = 0x40;
|
||||
|
||||
imx9_flexspi_nor_write_status(dev, &status);
|
||||
imx9_flexspi_nor_wait_bus_busy(dev);
|
||||
FLEXSPI_SOFTWARE_RESET(dev->flexspi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t imx9_flexspi_nor_read(struct mtd_dev_s *dev,
|
||||
off_t offset,
|
||||
size_t nbytes,
|
||||
@@ -825,7 +782,7 @@ static ssize_t imx9_flexspi_nor_read(struct mtd_dev_s *dev,
|
||||
(struct imx9_flexspi_nor_dev_s *)dev;
|
||||
uint8_t *src;
|
||||
|
||||
finfo("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes);
|
||||
finfo("Read offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes);
|
||||
|
||||
if (priv->port >= FLEXSPI_PORT_COUNT)
|
||||
{
|
||||
@@ -835,12 +792,15 @@ static ssize_t imx9_flexspi_nor_read(struct mtd_dev_s *dev,
|
||||
src = priv->ahb_base + offset;
|
||||
DEBUGASSERT(((uintptr_t)src & (ARMV8A_DCACHE_LINESIZE - 1)) == 0);
|
||||
|
||||
up_invalidate_dcache((uintptr_t)src,
|
||||
(uintptr_t)src +
|
||||
up_invalidate_dcache((uintptr_t)buffer,
|
||||
(uintptr_t)buffer +
|
||||
ALIGN_UP(nbytes, ARMV8A_DCACHE_LINESIZE));
|
||||
|
||||
memcpy(buffer, src, nbytes);
|
||||
|
||||
up_clean_dcache((uintptr_t)buffer, (uintptr_t)buffer +
|
||||
ALIGN_UP(nbytes, ARMV8A_DCACHE_LINESIZE));
|
||||
|
||||
finfo("return nbytes: %d\n", (int)nbytes);
|
||||
return (ssize_t)nbytes;
|
||||
}
|
||||
@@ -850,9 +810,9 @@ static ssize_t imx9_flexspi_nor_bread(struct mtd_dev_s *dev,
|
||||
size_t nblocks,
|
||||
uint8_t *buffer)
|
||||
{
|
||||
struct imx9_flexspi_nor_dev_s *priv =
|
||||
(struct imx9_flexspi_nor_dev_s *)dev;
|
||||
ssize_t nbytes;
|
||||
struct imx9_flexspi_nor_dev_s *priv =
|
||||
(struct imx9_flexspi_nor_dev_s *)dev;
|
||||
|
||||
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||
|
||||
@@ -860,14 +820,15 @@ static ssize_t imx9_flexspi_nor_bread(struct mtd_dev_s *dev,
|
||||
* read
|
||||
*/
|
||||
|
||||
nbytes = imx9_flexspi_nor_read(dev, startblock << priv->pageshift,
|
||||
nblocks << priv->pageshift, buffer);
|
||||
if (nbytes > 0)
|
||||
nbytes = imx9_flexspi_nor_read(dev, startblock << priv->subsectorshift,
|
||||
nblocks << priv->subsectorshift, buffer);
|
||||
|
||||
if (nbytes < 0)
|
||||
{
|
||||
nbytes >>= priv->pageshift;
|
||||
return nbytes;
|
||||
}
|
||||
|
||||
return nbytes;
|
||||
return nblocks;
|
||||
}
|
||||
|
||||
static ssize_t imx9_flexspi_nor_bwrite(struct mtd_dev_s *dev,
|
||||
@@ -878,16 +839,17 @@ static ssize_t imx9_flexspi_nor_bwrite(struct mtd_dev_s *dev,
|
||||
struct imx9_flexspi_nor_dev_s *priv =
|
||||
(struct imx9_flexspi_nor_dev_s *)dev;
|
||||
size_t pgsize = 1 << priv->pageshift;
|
||||
size_t len = nblocks << priv->pageshift;
|
||||
off_t offset = startblock << priv->pageshift;
|
||||
int i;
|
||||
size_t len = nblocks << priv->subsectorshift;
|
||||
off_t offset = startblock << priv->subsectorshift;
|
||||
|
||||
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||
int i = 0;
|
||||
|
||||
finfo("Wstartblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||
|
||||
while (len)
|
||||
{
|
||||
i = MIN(pgsize, len);
|
||||
imx9_flexspi_nor_write_enable(priv);
|
||||
imx9_flexspi_nor_write_cmd(priv, WRITE_ENABLE);
|
||||
imx9_flexspi_nor_page_program(priv, offset, src, i);
|
||||
imx9_flexspi_nor_wait_bus_busy(priv);
|
||||
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
|
||||
@@ -906,7 +868,6 @@ static int imx9_flexspi_nor_erase(struct mtd_dev_s *dev,
|
||||
struct imx9_flexspi_nor_dev_s *priv =
|
||||
(struct imx9_flexspi_nor_dev_s *)dev;
|
||||
size_t blocksleft = nblocks;
|
||||
uint8_t *dst = priv->ahb_base + (startblock << priv->subsectorshift);
|
||||
|
||||
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
|
||||
|
||||
@@ -914,7 +875,7 @@ static int imx9_flexspi_nor_erase(struct mtd_dev_s *dev,
|
||||
{
|
||||
/* Erase each sector */
|
||||
|
||||
imx9_flexspi_nor_write_enable(priv);
|
||||
imx9_flexspi_nor_write_cmd(priv, WRITE_ENABLE);
|
||||
imx9_flexspi_nor_erase_sector(priv,
|
||||
startblock << priv->subsectorshift);
|
||||
imx9_flexspi_nor_wait_bus_busy(priv);
|
||||
@@ -922,9 +883,6 @@ static int imx9_flexspi_nor_erase(struct mtd_dev_s *dev,
|
||||
startblock++;
|
||||
}
|
||||
|
||||
up_invalidate_dcache((uintptr_t)dst,
|
||||
(uintptr_t)dst + (nblocks << priv->subsectorshift));
|
||||
|
||||
return (int)nblocks;
|
||||
}
|
||||
|
||||
@@ -956,7 +914,11 @@ static int imx9_flexspi_nor_ioctl(struct mtd_dev_s *dev,
|
||||
* necessary to make it appear so.
|
||||
*/
|
||||
|
||||
geo->blocksize = (1 << priv->pageshift);
|
||||
/* We report 4k blocksize, that is more convient for upper
|
||||
* layers
|
||||
*/
|
||||
|
||||
geo->blocksize = (1 << priv->subsectorshift);
|
||||
#ifdef CONFIG_M25P_SUBSECTOR_ERASE
|
||||
if (priv->subsectorshift > 0)
|
||||
{
|
||||
@@ -988,8 +950,8 @@ static int imx9_flexspi_nor_ioctl(struct mtd_dev_s *dev,
|
||||
{
|
||||
/* Erase the entire device */
|
||||
|
||||
imx9_flexspi_nor_write_enable(priv);
|
||||
ret = imx9_flexspi_nor_erase_chip(priv);
|
||||
imx9_flexspi_nor_write_cmd(priv, WRITE_ENABLE);
|
||||
ret = imx9_flexspi_nor_write_cmd(priv, ERASE_CHIP);
|
||||
if (ret)
|
||||
{
|
||||
ferr("bulk erase failed\n");
|
||||
@@ -1040,6 +1002,8 @@ static int imx9_flexspi_nor_ioctl(struct mtd_dev_s *dev,
|
||||
|
||||
struct mtd_dev_s *imx9_flexspi_nor_initialize(int intf)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
|
||||
/* Configure multiplexed pins as connected on the board */
|
||||
|
||||
imx9_iomux_configure(MUX_FLEXSPI_IO0);
|
||||
@@ -1069,10 +1033,11 @@ struct mtd_dev_s *imx9_flexspi_nor_initialize(int intf)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (imx9_flexspi_nor_enable_quad_mode(&g_flexspi_nor))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
imx9_flexspi_nor_write_cmd(&g_flexspi_nor, ENTER_4BYTE);
|
||||
|
||||
imx9_flexspi_nor_read_register(&g_flexspi_nor, &val,
|
||||
1, READ_FLAG_STATUS_REG);
|
||||
finfo("Flag status register = 0x%x\n", val);
|
||||
|
||||
return &g_flexspi_nor.mtd;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user