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:
Jouni Ukkonen
2024-09-25 12:25:14 +03:00
committed by Xiang Xiao
parent d260e7f59e
commit a3d1b06214
2 changed files with 72 additions and 107 deletions
+2 -2
View File
@@ -1235,9 +1235,9 @@ struct flexspi_dev_s *imx9_flexspi_initialize(int intf)
imx9_ccm_gate_on(CCM_LPCG_FLEXSPI1, true); 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? */ /* Has the FlexSPI hardware been initialized? */
+70 -105
View File
@@ -246,12 +246,14 @@
#define M25P_BE 0xc7 /* 1 Bulk Erase 0 0 0 */ #define M25P_BE 0xc7 /* 1 Bulk Erase 0 0 0 */
#define M25P_DP 0xb9 /* 2 Deep power down 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_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_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 */ /* Quad commands */
#define M25P_Q_FAST_RD 0x6b /* 1 Quad output fast read 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 0x32 /* 1 Quad input fast program 3/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 */ #define M25P_Q_ENTER 0x35 /* 1 Enter Quad input/output 0 0 0 */
/* NOTE 1: All parts. /* NOTE 1: All parts.
@@ -260,18 +262,23 @@
* is a sector erase. * is a sector erase.
*/ */
#define ADDRESS_24BIT 0x18
#define ADDRESS_32BIT 0x20
enum enum
{ {
/* SPI instructions */ /* SPI instructions */
READ_ID, READ_ID,
READ_STATUS_REG, READ_STATUS_REG,
READ_FLAG_STATUS_REG,
WRITE_STATUS_REG, WRITE_STATUS_REG,
WRITE_ENABLE, WRITE_ENABLE,
ERASE_SECTOR, ERASE_SECTOR,
ERASE_CHIP, ERASE_CHIP,
ENTER_DDR, ENTER_DDR,
READ_FAST, READ_FAST,
ENTER_4BYTE,
/* Quad SPI instructions */ /* Quad SPI instructions */
@@ -296,6 +303,12 @@ static const uint32_t g_flexspi_nor_lut[][4] =
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04), 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] = [WRITE_STATUS_REG] =
{ {
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_WRSR, 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] = [ERASE_SECTOR] =
{ {
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_SSE, /* note: sub-sector erase */ 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] = [ERASE_CHIP] =
@@ -323,7 +336,7 @@ static const uint32_t g_flexspi_nor_lut[][4] =
[READ_FAST_QUAD_OUTPUT] = [READ_FAST_QUAD_OUTPUT] =
{ {
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_Q_FAST_RD, 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_LUT_SEQ(FLEXSPI_COMMAND_DUMMY_SDR, FLEXSPI_4PAD, 0x08,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_4PAD, 0x04), FLEXSPI_COMMAND_READ_SDR, FLEXSPI_4PAD, 0x04),
}, },
@@ -331,11 +344,17 @@ static const uint32_t g_flexspi_nor_lut[][4] =
[PAGE_PROGRAM_QUAD_INPUT] = [PAGE_PROGRAM_QUAD_INPUT] =
{ {
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_Q_FAST_PP, 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_LUT_SEQ(FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_4PAD, 0x04,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0), 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] = [ENTER_QPI] =
{ {
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_Q_ENTER, 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] = [READ_FAST] =
{ {
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, M25P_FAST_READ, 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_LUT_SEQ(FLEXSPI_COMMAND_DUMMY_SDR, FLEXSPI_1PAD, 0x08,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04) 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 = 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 */ .flash_size = 1024 * 64, /* size in kB */
.cs_interval_unit = FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE, .cs_interval_unit = FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE,
.cs_interval = 0, .cs_interval = 0,
@@ -627,9 +646,9 @@ static int imx9_flexspi_nor_get_id(
return -ENODEV; return -ENODEV;
} }
static int imx9_flexspi_nor_read_status( static int imx9_flexspi_nor_read_register(
const struct imx9_flexspi_nor_dev_s *dev, const struct imx9_flexspi_nor_dev_s *dev,
uint32_t *status) uint32_t *value, uint32_t len, int seq)
{ {
int stat; int stat;
@@ -639,8 +658,8 @@ static int imx9_flexspi_nor_read_status(
.port = dev->port, .port = dev->port,
.cmd_type = FLEXSPI_READ, .cmd_type = FLEXSPI_READ,
.seq_number = 1, .seq_number = 1,
.seq_index = READ_STATUS_REG, .seq_index = seq,
.data = status, .data = value,
.data_size = 1, .data_size = 1,
}; };
@@ -653,34 +672,9 @@ static int imx9_flexspi_nor_read_status(
return 0; return 0;
} }
static int imx9_flexspi_nor_write_status( static int imx9_flexspi_nor_write_cmd(
const struct imx9_flexspi_nor_dev_s *dev, const struct imx9_flexspi_nor_dev_s *dev,
uint32_t *status) int cmd)
{
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 stat; int stat;
@@ -690,7 +684,7 @@ static int imx9_flexspi_nor_write_enable(
.port = dev->port, .port = dev->port,
.cmd_type = FLEXSPI_COMMAND, .cmd_type = FLEXSPI_COMMAND,
.seq_number = 1, .seq_number = 1,
.seq_index = WRITE_ENABLE, .seq_index = cmd,
.data = NULL, .data = NULL,
.data_size = 0, .data_size = 0,
}; };
@@ -730,31 +724,6 @@ static int imx9_flexspi_nor_erase_sector(
return 0; 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( static int imx9_flexspi_nor_page_program(
const struct imx9_flexspi_nor_dev_s *dev, const struct imx9_flexspi_nor_dev_s *dev,
off_t offset, off_t offset,
@@ -793,7 +762,7 @@ static int imx9_flexspi_nor_wait_bus_busy(
do do
{ {
ret = imx9_flexspi_nor_read_status(dev, &status); ret = imx9_flexspi_nor_read_register(dev, &status, 1, READ_STATUS_REG);
if (ret) if (ret)
{ {
return ret; return ret;
@@ -804,18 +773,6 @@ static int imx9_flexspi_nor_wait_bus_busy(
return 0; 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, static ssize_t imx9_flexspi_nor_read(struct mtd_dev_s *dev,
off_t offset, off_t offset,
size_t nbytes, 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; (struct imx9_flexspi_nor_dev_s *)dev;
uint8_t *src; 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) 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; src = priv->ahb_base + offset;
DEBUGASSERT(((uintptr_t)src & (ARMV8A_DCACHE_LINESIZE - 1)) == 0); DEBUGASSERT(((uintptr_t)src & (ARMV8A_DCACHE_LINESIZE - 1)) == 0);
up_invalidate_dcache((uintptr_t)src, up_invalidate_dcache((uintptr_t)buffer,
(uintptr_t)src + (uintptr_t)buffer +
ALIGN_UP(nbytes, ARMV8A_DCACHE_LINESIZE)); ALIGN_UP(nbytes, ARMV8A_DCACHE_LINESIZE));
memcpy(buffer, src, nbytes); 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); finfo("return nbytes: %d\n", (int)nbytes);
return (ssize_t)nbytes; return (ssize_t)nbytes;
} }
@@ -850,9 +810,9 @@ static ssize_t imx9_flexspi_nor_bread(struct mtd_dev_s *dev,
size_t nblocks, size_t nblocks,
uint8_t *buffer) uint8_t *buffer)
{ {
struct imx9_flexspi_nor_dev_s *priv =
(struct imx9_flexspi_nor_dev_s *)dev;
ssize_t nbytes; 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); 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 * read
*/ */
nbytes = imx9_flexspi_nor_read(dev, startblock << priv->pageshift, nbytes = imx9_flexspi_nor_read(dev, startblock << priv->subsectorshift,
nblocks << priv->pageshift, buffer); nblocks << priv->subsectorshift, buffer);
if (nbytes > 0)
if (nbytes < 0)
{ {
nbytes >>= priv->pageshift; return nbytes;
} }
return nbytes; return nblocks;
} }
static ssize_t imx9_flexspi_nor_bwrite(struct mtd_dev_s *dev, 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 *priv =
(struct imx9_flexspi_nor_dev_s *)dev; (struct imx9_flexspi_nor_dev_s *)dev;
size_t pgsize = 1 << priv->pageshift; size_t pgsize = 1 << priv->pageshift;
size_t len = nblocks << priv->pageshift; size_t len = nblocks << priv->subsectorshift;
off_t offset = startblock << priv->pageshift; off_t offset = startblock << priv->subsectorshift;
int i;
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) while (len)
{ {
i = MIN(pgsize, 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_page_program(priv, offset, src, i);
imx9_flexspi_nor_wait_bus_busy(priv); imx9_flexspi_nor_wait_bus_busy(priv);
FLEXSPI_SOFTWARE_RESET(priv->flexspi); 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 *priv =
(struct imx9_flexspi_nor_dev_s *)dev; (struct imx9_flexspi_nor_dev_s *)dev;
size_t blocksleft = nblocks; size_t blocksleft = nblocks;
uint8_t *dst = priv->ahb_base + (startblock << priv->subsectorshift);
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks); 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 */ /* Erase each sector */
imx9_flexspi_nor_write_enable(priv); imx9_flexspi_nor_write_cmd(priv, WRITE_ENABLE);
imx9_flexspi_nor_erase_sector(priv, imx9_flexspi_nor_erase_sector(priv,
startblock << priv->subsectorshift); startblock << priv->subsectorshift);
imx9_flexspi_nor_wait_bus_busy(priv); imx9_flexspi_nor_wait_bus_busy(priv);
@@ -922,9 +883,6 @@ static int imx9_flexspi_nor_erase(struct mtd_dev_s *dev,
startblock++; startblock++;
} }
up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + (nblocks << priv->subsectorshift));
return (int)nblocks; return (int)nblocks;
} }
@@ -956,7 +914,11 @@ static int imx9_flexspi_nor_ioctl(struct mtd_dev_s *dev,
* necessary to make it appear so. * 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 #ifdef CONFIG_M25P_SUBSECTOR_ERASE
if (priv->subsectorshift > 0) if (priv->subsectorshift > 0)
{ {
@@ -988,8 +950,8 @@ static int imx9_flexspi_nor_ioctl(struct mtd_dev_s *dev,
{ {
/* Erase the entire device */ /* Erase the entire device */
imx9_flexspi_nor_write_enable(priv); imx9_flexspi_nor_write_cmd(priv, WRITE_ENABLE);
ret = imx9_flexspi_nor_erase_chip(priv); ret = imx9_flexspi_nor_write_cmd(priv, ERASE_CHIP);
if (ret) if (ret)
{ {
ferr("bulk erase failed\n"); 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) struct mtd_dev_s *imx9_flexspi_nor_initialize(int intf)
{ {
uint32_t val = 0;
/* Configure multiplexed pins as connected on the board */ /* Configure multiplexed pins as connected on the board */
imx9_iomux_configure(MUX_FLEXSPI_IO0); imx9_iomux_configure(MUX_FLEXSPI_IO0);
@@ -1069,10 +1033,11 @@ struct mtd_dev_s *imx9_flexspi_nor_initialize(int intf)
return NULL; return NULL;
} }
if (imx9_flexspi_nor_enable_quad_mode(&g_flexspi_nor)) imx9_flexspi_nor_write_cmd(&g_flexspi_nor, ENTER_4BYTE);
{
return NULL; 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; return &g_flexspi_nor.mtd;
} }