Skip to content

Commit

Permalink
arch/arm64/imx9 4byte addressing to nor
Browse files Browse the repository at this point in the history
-Use 4byte addressing in flexpi nor
-report 4k blocksize to userland
-increase clock to 100MHz
-some cleanup

Signed-off-by: Jouni Ukkonen <[email protected]>
  • Loading branch information
joukkone committed Sep 25, 2024
1 parent a6a81be commit b2393e9
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 80 deletions.
4 changes: 2 additions & 2 deletions arch/arm64/src/imx9/imx9_flexspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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? */

Expand Down
142 changes: 64 additions & 78 deletions arch/arm64/src/imx9/imx9_flexspi_nor.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,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 0 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 3/4 0 1-256 */
#define M25P_Q_FAST_PP 0x34 /* 1 Quad input fast program 3/4 0 1-256 */
#define M25P_Q_ENTER 0x35 /* 1 Enter Quad input/output 0 0 0 */

/* NOTE 1: All parts.
Expand All @@ -268,12 +270,14 @@ enum

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

Expand All @@ -298,6 +302,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,
Expand All @@ -313,7 +323,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, 0x20),
},

[ERASE_CHIP] =
Expand All @@ -325,19 +335,25 @@ 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, 0x20),
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_DUMMY_SDR, FLEXSPI_4PAD, 0x08,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_4PAD, 0x04),
},

[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, 0x20),
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,
Expand Down Expand Up @@ -412,7 +428,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,
Expand Down Expand Up @@ -629,9 +645,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;

Expand All @@ -641,8 +657,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,
};

Expand All @@ -655,34 +671,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;

Expand All @@ -692,7 +683,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,
};
Expand Down Expand Up @@ -795,7 +786,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;
Expand All @@ -806,18 +797,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,
Expand All @@ -827,7 +806,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)
{
Expand All @@ -837,11 +816,13 @@ static ssize_t imx9_flexspi_nor_read(struct mtd_dev_s *dev,
src = priv->ahb_base + offset;
DEBUGASSERT(((uintptr_t)src & ALIGN_MASK) == 0);

up_invalidate_dcache((uintptr_t)src,
(uintptr_t)src + ALIGN_UP(nbytes));
up_invalidate_dcache((uintptr_t)buffer,
(uintptr_t)buffer + ALIGN_UP(nbytes));

memcpy(buffer, src, nbytes);

up_clean_dcache((uintptr_t)buffer, (uintptr_t)buffer + ALIGN_UP(nbytes));

finfo("return nbytes: %d\n", (int)nbytes);
return (ssize_t)nbytes;
}
Expand All @@ -851,24 +832,25 @@ 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);

/* On this device, we can handle the block read just like the byte-oriented
* 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,
Expand All @@ -879,16 +861,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);
Expand All @@ -907,25 +890,21 @@ 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);

while (blocksleft-- > 0)
{
/* 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);
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
startblock++;
}

up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + (nblocks << priv->subsectorshift));

return (int)nblocks;
}

Expand Down Expand Up @@ -957,7 +936,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)
{
Expand Down Expand Up @@ -989,7 +972,7 @@ static int imx9_flexspi_nor_ioctl(struct mtd_dev_s *dev,
{
/* 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);
if (ret)
{
Expand Down Expand Up @@ -1041,6 +1024,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);
Expand Down Expand Up @@ -1070,10 +1055,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;
}
Expand Down

0 comments on commit b2393e9

Please sign in to comment.