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);
/* 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? */
+70 -105
View File
@@ -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;
}