Removing FLexSPI NOR driver

This commit is contained in:
jturnsek 2021-04-12 20:33:15 +02:00 committed by Alan Carvalho de Assis
parent 177ff946b8
commit f57ff30545
6 changed files with 0 additions and 1905 deletions

View File

@ -1,701 +0,0 @@
/****************************************************************************
* boards/arm/imxrt/imxrt1064-evk/src/imxrt_flexspi_nor.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdbool.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/signal.h>
#include <nuttx/fs/fs.h>
#include <nuttx/mtd/mtd.h>
#include "imxrt_flexspi.h"
#include "imxrt1064-evk.h"
#include "hardware/imxrt_pinmux.h"
#ifdef CONFIG_IMXRT_FLEXSPI
#define NOR_PAGE_SIZE 0x0100U
#define NOR_SECTOR_SIZE 0x1000U
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
enum
{
/* SPI instructions */
READ_ID,
READ_STATUS_REG,
WRITE_STATUS_REG,
WRITE_ENABLE,
ERASE_SECTOR,
ERASE_CHIP,
/* Quad SPI instructions */
READ_FAST_QUAD_OUTPUT,
PAGE_PROGRAM_QUAD_INPUT,
ENTER_QPI,
};
static const uint32_t g_flexspi_nor_lut[][4] =
{
[READ_ID] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x9f,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04),
},
[READ_STATUS_REG] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x05,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04),
},
[WRITE_STATUS_REG] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x01,
FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_1PAD, 0x04),
},
[WRITE_ENABLE] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x06,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[ERASE_SECTOR] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x20,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
},
[ERASE_CHIP] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0xc7,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[READ_FAST_QUAD_OUTPUT] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x6b,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
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, 0x32,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_4PAD, 0x04,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[ENTER_QPI] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x35,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
};
/****************************************************************************
* Private Types
****************************************************************************/
/* FlexSPI NOR device private data */
struct imxrt_flexspi_nor_dev_s
{
struct mtd_dev_s mtd;
struct flexspi_dev_s *flexspi; /* Saved FlexSPI interface instance */
uint8_t *ahb_base;
enum flexspi_port_e port;
struct flexspi_device_config_s *config;
};
/****************************************************************************
* Private Functions Prototypes
****************************************************************************/
/* MTD driver methods */
static int imxrt_flexspi_nor_erase(FAR struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks);
static ssize_t imxrt_flexspi_nor_read(FAR struct mtd_dev_s *dev,
off_t offset,
size_t nbytes,
FAR uint8_t *buffer);
static ssize_t imxrt_flexspi_nor_bread(FAR struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks,
FAR uint8_t *buffer);
static ssize_t imxrt_flexspi_nor_bwrite(FAR struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks,
FAR const uint8_t *buffer);
static int imxrt_flexspi_nor_ioctl(FAR struct mtd_dev_s *dev,
int cmd,
unsigned long arg);
/****************************************************************************
* Private Data
****************************************************************************/
static struct flexspi_device_config_s g_flexspi_device_config =
{
.flexspi_root_clk = 120000000,
.flash_size = 8192,
.cs_interval_unit = FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE,
.cs_interval = 0,
.cs_hold_time = 3,
.cs_setup_time = 3,
.data_valid_time = 0,
.columnspace = 0,
.enable_word_address = 0,
.awr_seq_index = 0,
.awr_seq_number = 0,
.ard_seq_index = READ_FAST_QUAD_OUTPUT,
.ard_seq_number = 1,
.ahb_write_wait_unit = FLEXSPI_AHB_WRITE_WAIT_UNIT2_AHB_CYCLE,
.ahb_write_wait_interval = 0
};
static struct imxrt_flexspi_nor_dev_s g_flexspi_nor =
{
.mtd =
{
.erase = imxrt_flexspi_nor_erase,
.bread = imxrt_flexspi_nor_bread,
.bwrite = imxrt_flexspi_nor_bwrite,
.read = imxrt_flexspi_nor_read,
.ioctl = imxrt_flexspi_nor_ioctl,
#ifdef CONFIG_MTD_BYTE_WRITE
.write = NULL,
#endif
.name = "imxrt_flexspi_nor"
},
.flexspi = (void *)0,
.ahb_base = (uint8_t *) 0x60000000,
.port = FLEXSPI_PORT_A1,
.config = &g_flexspi_device_config
};
/****************************************************************************
* Private Functions
****************************************************************************/
static int imxrt_flexspi_nor_get_vendor_id(
const struct imxrt_flexspi_nor_dev_s *dev,
uint8_t *vendor_id)
{
uint32_t buffer = 0;
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = 0,
.port = dev->port,
.cmd_type = FLEXSPI_READ,
.seq_number = 1,
.seq_index = READ_ID,
.data = &buffer,
.data_size = 1,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
*vendor_id = buffer;
return 0;
}
static int imxrt_flexspi_nor_read_status(
const struct imxrt_flexspi_nor_dev_s *dev,
uint32_t *status)
{
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = 0,
.port = dev->port,
.cmd_type = FLEXSPI_READ,
.seq_number = 1,
.seq_index = READ_STATUS_REG,
.data = status,
.data_size = 1,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int imxrt_flexspi_nor_write_status(
const struct imxrt_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 imxrt_flexspi_nor_write_enable(
const struct imxrt_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 = WRITE_ENABLE,
.data = NULL,
.data_size = 0,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int imxrt_flexspi_nor_erase_sector(
const struct imxrt_flexspi_nor_dev_s *dev,
off_t offset)
{
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = offset,
.port = dev->port,
.cmd_type = FLEXSPI_COMMAND,
.seq_number = 1,
.seq_index = ERASE_SECTOR,
.data = NULL,
.data_size = 0,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int imxrt_flexspi_nor_erase_chip(
const struct imxrt_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 imxrt_flexspi_nor_page_program(
const struct imxrt_flexspi_nor_dev_s *dev,
off_t offset,
const void *buffer,
size_t len)
{
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = offset,
.port = dev->port,
.cmd_type = FLEXSPI_WRITE,
.seq_number = 1,
.seq_index = PAGE_PROGRAM_QUAD_INPUT,
.data = (uint32_t *) buffer,
.data_size = len,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int imxrt_flexspi_nor_wait_bus_busy(
const struct imxrt_flexspi_nor_dev_s *dev)
{
uint32_t status = 0;
int ret;
do
{
ret = imxrt_flexspi_nor_read_status(dev, &status);
if (ret)
{
return ret;
}
}
while (status & 1);
return 0;
}
static int imxrt_flexspi_nor_enable_quad_mode(
const struct imxrt_flexspi_nor_dev_s *dev)
{
uint32_t status = 0x40;
imxrt_flexspi_nor_write_status(dev, &status);
imxrt_flexspi_nor_wait_bus_busy(dev);
FLEXSPI_SOFTWARE_RESET(dev->flexspi);
return 0;
}
static ssize_t imxrt_flexspi_nor_read(FAR struct mtd_dev_s *dev,
off_t offset,
size_t nbytes,
FAR uint8_t *buffer)
{
FAR struct imxrt_flexspi_nor_dev_s *priv =
(FAR struct imxrt_flexspi_nor_dev_s *)dev;
uint8_t *src;
finfo("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes);
if (priv->port >= FLEXSPI_PORT_COUNT)
{
return -EIO;
}
src = priv->ahb_base + offset;
memcpy(buffer, src, nbytes);
finfo("return nbytes: %d\n", (int)nbytes);
return (ssize_t)nbytes;
}
static ssize_t imxrt_flexspi_nor_bread(FAR struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks,
FAR uint8_t *buffer)
{
ssize_t nbytes;
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 = imxrt_flexspi_nor_read(dev, startblock * NOR_PAGE_SIZE,
nblocks * NOR_PAGE_SIZE, buffer);
if (nbytes > 0)
{
nbytes /= NOR_PAGE_SIZE;
}
return nbytes;
}
static ssize_t imxrt_flexspi_nor_bwrite(FAR struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks,
FAR const uint8_t *buffer)
{
FAR struct imxrt_flexspi_nor_dev_s *priv =
(FAR struct imxrt_flexspi_nor_dev_s *)dev;
size_t len = nblocks * NOR_PAGE_SIZE;
off_t offset = startblock * NOR_PAGE_SIZE;
uint8_t *src = (uint8_t *) buffer;
uint8_t *dst = priv->ahb_base + startblock * NOR_PAGE_SIZE;
int i;
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
while (len)
{
i = MIN(NOR_PAGE_SIZE, len);
imxrt_flexspi_nor_write_enable(priv);
imxrt_flexspi_nor_page_program(priv, offset, src, i);
imxrt_flexspi_nor_wait_bus_busy(priv);
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
offset += i;
len -= i;
}
#ifdef CONFIG_ARMV7M_DCACHE
up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + nblocks * NOR_PAGE_SIZE);
#endif
return nblocks;
}
static int imxrt_flexspi_nor_erase(FAR struct mtd_dev_s *dev,
off_t startblock,
size_t nblocks)
{
FAR struct imxrt_flexspi_nor_dev_s *priv =
(FAR struct imxrt_flexspi_nor_dev_s *)dev;
size_t blocksleft = nblocks;
uint8_t *dst = priv->ahb_base + startblock * NOR_SECTOR_SIZE;
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
while (blocksleft-- > 0)
{
/* Erase each sector */
imxrt_flexspi_nor_write_enable(priv);
imxrt_flexspi_nor_erase_sector(priv, startblock * NOR_SECTOR_SIZE);
imxrt_flexspi_nor_wait_bus_busy(priv);
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
startblock++;
}
#ifdef CONFIG_ARMV7M_DCACHE
up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + nblocks * NOR_SECTOR_SIZE);
#endif
return (int)nblocks;
}
static int imxrt_flexspi_nor_ioctl(FAR struct mtd_dev_s *dev,
int cmd,
unsigned long arg)
{
FAR struct imxrt_flexspi_nor_dev_s *priv =
(FAR struct imxrt_flexspi_nor_dev_s *)dev;
int ret = -EINVAL; /* Assume good command with bad parameters */
finfo("cmd: %d \n", cmd);
switch (cmd)
{
case MTDIOC_GEOMETRY:
{
FAR struct mtd_geometry_s *geo =
(FAR struct mtd_geometry_s *)((uintptr_t)arg);
if (geo)
{
/* Populate the geometry structure with information need to
* know the capacity and how to access the device.
*
* NOTE:
* that the device is treated as though it where just an array
* of fixed size blocks. That is most likely not true, but the
* client will expect the device logic to do whatever is
* necessary to make it appear so.
*/
geo->blocksize = (NOR_PAGE_SIZE);
geo->erasesize = (NOR_SECTOR_SIZE);
geo->neraseblocks = 2048; /* 8MB only */
ret = OK;
finfo("blocksize: %lu erasesize: %lu neraseblocks: %lu\n",
geo->blocksize, geo->erasesize, geo->neraseblocks);
}
}
break;
case MTDIOC_BULKERASE:
{
/* Erase the entire device */
imxrt_flexspi_nor_write_enable(priv);
imxrt_flexspi_nor_erase_chip(priv);
imxrt_flexspi_nor_wait_bus_busy(priv);
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
}
break;
case MTDIOC_PROTECT:
/* TODO */
break;
case MTDIOC_UNPROTECT:
/* TODO */
break;
default:
ret = -ENOTTY; /* Bad/unsupported command */
break;
}
finfo("return %d\n", ret);
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: imxrt_flexspi_nor_initialize
*
* Description:
* This function is called by board-bringup logic to configure the
* flash device.
*
* Returned Value:
* Zero is returned on success. Otherwise, a negated errno value is
* returned to indicate the nature of the failure.
*
****************************************************************************/
int imxrt_flexspi_nor_initialize(void)
{
uint8_t vendor_id;
#ifdef CONFIG_FS_LITTLEFS
FAR struct mtd_dev_s *mtd_dev = &g_flexspi_nor.mtd;
int ret = -1;
#endif
/* Configure multiplexed pins as connected on the board */
imxrt_config_gpio(GPIO_FLEXSPI_DQS);
imxrt_config_gpio(GPIO_FLEXSPI_CS);
imxrt_config_gpio(GPIO_FLEXSPI_IO0);
imxrt_config_gpio(GPIO_FLEXSPI_IO1);
imxrt_config_gpio(GPIO_FLEXSPI_IO2);
imxrt_config_gpio(GPIO_FLEXSPI_IO3);
imxrt_config_gpio(GPIO_FLEXSPI_SCK);
g_flexspi_nor.flexspi = imxrt_flexspi_initialize(0);
if (!g_flexspi_nor.flexspi)
{
return -1;
}
FLEXSPI_SET_DEVICE_CONFIG(g_flexspi_nor.flexspi,
g_flexspi_nor.config,
g_flexspi_nor.port);
FLEXSPI_UPDATE_LUT(g_flexspi_nor.flexspi,
0,
(const uint32_t *)g_flexspi_nor_lut,
sizeof(g_flexspi_nor_lut) / 4);
FLEXSPI_SOFTWARE_RESET(g_flexspi_nor.flexspi);
if (imxrt_flexspi_nor_get_vendor_id(&g_flexspi_nor, &vendor_id))
{
return -EIO;
}
if (imxrt_flexspi_nor_enable_quad_mode(&g_flexspi_nor))
{
return -EIO;
}
#ifdef CONFIG_FS_LITTLEFS
/* Register the MTD driver so that it can be accessed from the
* VFS.
*/
ret = register_mtddriver("/dev/nor", mtd_dev, 0755, NULL);
if (ret < 0)
{
syslog(LOG_ERR, "ERROR: Failed to register MTD driver: %d\n",
ret);
}
/* mtd_dev->ioctl(mtd_dev, MTDIOC_BULKERASE, 0); */
/* Mount the LittleFS file system */
ret = nx_mount("/dev/nor", "/mnt/lfs", "littlefs", 0,
"autoformat");
if (ret < 0)
{
syslog(LOG_ERR,
"ERROR: Failed to mount LittleFS at /mnt/lfs: %d\n",
ret);
}
#endif
return 0;
}
#endif /* CONFIG_IMXRT_FLEXSPI */

View File

@ -655,25 +655,6 @@ config W25QXXXJV_SECTOR512
endif # MTD_W25QXXXJV
config MTD_FLEXSPI_NOR
bool "FlexSPI-based NOR FLASH"
default n
---help---
Support the W25Q064JV, WIS25WP064
if MTD_FLEXSPI_NOR
config FLEXSPI_NOR_FREQUENCY
int "FlexSPI NOR Frequency"
default 133000000
---help---
Per data sheet:
133MHz Single, Dual/Quad SPI clocks
266/532MHz equivalent Dual/Quad SPI
66MB/S continuous data transfer rate
endif # MTD_FLEXSPI_NOR
config MTD_MX25RXX
bool "QuadSPI-based Macronix MX25RXX family FLASH"
default n

View File

@ -140,10 +140,6 @@ ifeq ($(CONFIG_MTD_IS25XP),y)
CSRCS += is25xp.c
endif
ifeq ($(CONFIG_MTD_FLEXSPI_NOR),y)
CSRCS += flexspi_nor.c
endif
ifeq ($(CONFIG_MTD_SMART),y)
ifeq ($(CONFIG_FS_SMARTFS),y)
CSRCS += smart.c

View File

@ -1,647 +0,0 @@
/****************************************************************************
* drivers/mtd/flexspi_nor.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/kmalloc.h>
#include <nuttx/signal.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/spi/flexspi.h>
#include <nuttx/mtd/mtd.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
/* Configuration ************************************************************/
#define NOR_PAGE_SIZE 0x0100U
#define NOR_SECTOR_SIZE 0x1000U
/* This type represents the state of the MTD device. The struct mtd_dev_s
* must appear at the beginning of the definition so that you can freely
* cast between pointers to struct mtd_dev_s and struct flexspi_nor_dev_s.
*/
struct flexspi_nor_dev_s
{
struct mtd_dev_s mtd;
FAR struct flexspi_dev_s *flexspi; /* Saved FlexSPI interface instance */
uint8_t *ahb_base;
enum flexspi_port_e port;
struct flexspi_device_config_s config;
};
enum
{
/* SPI instructions */
READ_ID,
READ_STATUS_REG,
WRITE_STATUS_REG,
WRITE_ENABLE,
ERASE_SECTOR,
ERASE_CHIP,
/* Quad SPI instructions */
READ_FAST_QUAD_OUTPUT,
PAGE_PROGRAM_QUAD_INPUT,
ENTER_QPI,
};
static const uint32_t flexspi_nor_lut[][4] =
{
[READ_ID] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x9f,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04),
},
[READ_STATUS_REG] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x05,
FLEXSPI_COMMAND_READ_SDR, FLEXSPI_1PAD, 0x04),
},
[WRITE_STATUS_REG] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x01,
FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_1PAD, 0x04),
},
[WRITE_ENABLE] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x06,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[ERASE_SECTOR] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x20,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
},
[ERASE_CHIP] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0xc7,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[READ_FAST_QUAD_OUTPUT] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x6b,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
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, 0x32,
FLEXSPI_COMMAND_RADDR_SDR, FLEXSPI_1PAD, 0x18),
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_WRITE_SDR, FLEXSPI_4PAD, 0x04,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
[ENTER_QPI] =
{
FLEXSPI_LUT_SEQ(FLEXSPI_COMMAND_SDR, FLEXSPI_1PAD, 0x35,
FLEXSPI_COMMAND_STOP, FLEXSPI_1PAD, 0),
},
};
static int flexspi_nor_get_vendor_id(const struct flexspi_nor_dev_s *dev,
uint8_t *vendor_id)
{
uint32_t buffer = 0;
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = 0,
.port = dev->port,
.cmd_type = FLEXSPI_READ,
.seq_number = 1,
.seq_index = READ_ID,
.data = &buffer,
.data_size = 1,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
*vendor_id = buffer;
return 0;
}
static int flexspi_nor_read_status(const struct flexspi_nor_dev_s *dev,
uint32_t *status)
{
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = 0,
.port = dev->port,
.cmd_type = FLEXSPI_READ,
.seq_number = 1,
.seq_index = READ_STATUS_REG,
.data = status,
.data_size = 1,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int flexspi_nor_write_status(const struct 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 flexspi_nor_write_enable(const struct 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 = WRITE_ENABLE,
.data = NULL,
.data_size = 0,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int flexspi_nor_erase_sector(const struct flexspi_nor_dev_s *dev,
off_t offset)
{
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = offset,
.port = dev->port,
.cmd_type = FLEXSPI_COMMAND,
.seq_number = 1,
.seq_index = ERASE_SECTOR,
.data = NULL,
.data_size = 0,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int flexspi_nor_erase_chip(const struct 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 flexspi_nor_page_program(const struct flexspi_nor_dev_s *dev,
off_t offset, const void *buffer, size_t len)
{
int stat;
struct flexspi_transfer_s transfer =
{
.device_address = offset,
.port = dev->port,
.cmd_type = FLEXSPI_WRITE,
.seq_number = 1,
.seq_index = PAGE_PROGRAM_QUAD_INPUT,
.data = (uint32_t *) buffer,
.data_size = len,
};
stat = FLEXSPI_TRANSFER(dev->flexspi, &transfer);
if (stat != 0)
{
return -EIO;
}
return 0;
}
static int flexspi_nor_wait_bus_busy(const struct flexspi_nor_dev_s *dev)
{
uint32_t status = 0;
int ret;
do
{
ret = flexspi_nor_read_status(dev, &status);
if (ret)
{
return ret;
}
}
while (status & 1);
return 0;
}
static int flexspi_nor_enable_quad_mode(const struct flexspi_nor_dev_s *dev)
{
uint32_t status = 0x40;
flexspi_nor_write_status(dev, &status);
flexspi_nor_wait_bus_busy(dev);
FLEXSPI_SOFTWARE_RESET(dev->flexspi);
return 0;
}
static ssize_t flexspi_nor_read(FAR struct mtd_dev_s *dev,
off_t offset,
size_t nbytes,
FAR uint8_t *buffer)
{
FAR struct flexspi_nor_dev_s *priv = (FAR struct flexspi_nor_dev_s *)dev;
uint8_t *src;
finfo("offset: %08lx nbytes: %d\n", (long)offset, (int)nbytes);
if (priv->port >= FLEXSPI_PORT_COUNT)
{
return -EIO;
}
src = priv->ahb_base + offset;
memcpy(buffer, src, nbytes);
finfo("return nbytes: %d\n", (int)nbytes);
return (ssize_t)nbytes;
}
static ssize_t flexspi_nor_bread(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks, FAR uint8_t *buffer)
{
ssize_t nbytes;
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 = flexspi_nor_read(dev, startblock * NOR_PAGE_SIZE,
nblocks * NOR_PAGE_SIZE, buffer);
if (nbytes > 0)
{
nbytes /= NOR_PAGE_SIZE;
}
return nbytes;
}
static ssize_t flexspi_nor_bwrite(FAR struct mtd_dev_s *dev,
off_t startblock, size_t nblocks,
FAR const uint8_t *buffer)
{
FAR struct flexspi_nor_dev_s *priv = (FAR struct flexspi_nor_dev_s *)dev;
size_t len = nblocks * NOR_PAGE_SIZE;
off_t offset = startblock * NOR_PAGE_SIZE;
uint8_t *src = (uint8_t *) buffer;
uint8_t *dst = priv->ahb_base + startblock * NOR_PAGE_SIZE;
int i;
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
while (len)
{
i = MIN(NOR_PAGE_SIZE, len);
flexspi_nor_write_enable(priv);
flexspi_nor_page_program(priv, offset, src, i);
flexspi_nor_wait_bus_busy(priv);
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
offset += i;
len -= i;
}
#ifdef CONFIG_ARMV7M_DCACHE
up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + nblocks * NOR_PAGE_SIZE);
#endif
return nblocks;
}
static int flexspi_nor_erase(FAR struct mtd_dev_s *dev, off_t startblock,
size_t nblocks)
{
FAR struct flexspi_nor_dev_s *priv = (FAR struct flexspi_nor_dev_s *)dev;
size_t blocksleft = nblocks;
uint8_t *dst = priv->ahb_base + startblock * NOR_SECTOR_SIZE;
finfo("startblock: %08lx nblocks: %d\n", (long)startblock, (int)nblocks);
while (blocksleft-- > 0)
{
/* Erase each sector */
flexspi_nor_write_enable(priv);
flexspi_nor_erase_sector(priv, startblock * NOR_SECTOR_SIZE);
flexspi_nor_wait_bus_busy(priv);
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
startblock++;
}
#ifdef CONFIG_ARMV7M_DCACHE
up_invalidate_dcache((uintptr_t)dst,
(uintptr_t)dst + nblocks * NOR_SECTOR_SIZE);
#endif
return (int)nblocks;
}
static int flexspi_nor_ioctl(FAR struct mtd_dev_s *dev,
int cmd,
unsigned long arg)
{
FAR struct flexspi_nor_dev_s *priv = (FAR struct flexspi_nor_dev_s *)dev;
int ret = -EINVAL; /* Assume good command with bad parameters */
finfo("cmd: %d \n", cmd);
switch (cmd)
{
case MTDIOC_GEOMETRY:
{
FAR struct mtd_geometry_s *geo =
(FAR struct mtd_geometry_s *)((uintptr_t)arg);
if (geo)
{
/* Populate the geometry structure with information need to
* know the capacity and how to access the device.
*
* NOTE:
* that the device is treated as though it where just an array
* of fixed size blocks. That is most likely not true, but the
* client will expect the device logic to do whatever is
* necessary to make it appear so.
*/
geo->blocksize = (NOR_PAGE_SIZE);
geo->erasesize = (NOR_SECTOR_SIZE);
geo->neraseblocks = 2048; /* 8MB only */
ret = OK;
finfo("blocksize: %lu erasesize: %lu neraseblocks: %lu\n",
geo->blocksize, geo->erasesize, geo->neraseblocks);
}
}
break;
case MTDIOC_BULKERASE:
{
/* Erase the entire device */
flexspi_nor_write_enable(priv);
flexspi_nor_erase_chip(priv);
flexspi_nor_wait_bus_busy(priv);
FLEXSPI_SOFTWARE_RESET(priv->flexspi);
}
break;
case MTDIOC_PROTECT:
/* TODO */
break;
case MTDIOC_UNPROTECT:
/* TODO */
break;
default:
ret = -ENOTTY; /* Bad/unsupported command */
break;
}
finfo("return %d\n", ret);
return ret;
}
static int flexspi_nor_init(const struct flexspi_nor_dev_s *dev)
{
uint8_t vendor_id;
struct flexspi_device_config_s device_config;
if (dev->port >= FLEXSPI_PORT_COUNT)
{
return -EINVAL;
}
device_config.flexspi_root_clk = 120000000;
device_config.flash_size = 8192;
device_config.cs_interval_unit = FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE;
device_config.cs_interval = 0;
device_config.cs_hold_time = 3;
device_config.cs_setup_time = 3;
device_config.data_valid_time = 0;
device_config.columnspace = 0;
device_config.enable_word_address = 0;
device_config.awr_seq_index = 0;
device_config.awr_seq_number = 0;
device_config.ard_seq_index = READ_FAST_QUAD_OUTPUT;
device_config.ard_seq_number = 1;
device_config.ahb_write_wait_unit = FLEXSPI_AHB_WRITE_WAIT_UNIT2_AHB_CYCLE;
device_config.ahb_write_wait_interval = 0;
FLEXSPI_SET_DEVICE_CONFIG(dev->flexspi,
(struct flexspi_device_config_s *) &device_config,
dev->port);
FLEXSPI_UPDATE_LUT(dev->flexspi, 0, (const uint32_t *)flexspi_nor_lut,
sizeof(flexspi_nor_lut) / 4);
FLEXSPI_SOFTWARE_RESET(dev->flexspi);
if (flexspi_nor_get_vendor_id(dev, &vendor_id))
{
return -EIO;
}
if (flexspi_nor_enable_quad_mode(dev))
{
return -EIO;
}
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: flexspi_nor_initialize
*
* Description:
* Create an initialize MTD device instance for the FlexSPI-based NOR
* FLASH part.
*
* MTD devices are not registered in the file system, but are created as
* instances that can be bound to other functions (such as a block or
* character driver front end).
*
****************************************************************************/
FAR struct mtd_dev_s *flexspi_nor_initialize(struct flexspi_dev_s *flexspi,
bool unprotect)
{
FAR struct flexspi_nor_dev_s *priv;
int ret;
finfo("flexspi: %p\n", flexspi);
DEBUGASSERT(flexspi != NULL);
/* Allocate a state structure (we allocate the structure instead of using
* a fixed, static allocation so that we can handle multiple FLASH devices.
* The current implementation would handle only one FLASH part per FlexSPI
* device (only because of the FLEXSPI_DEV_FLASH(0) definition) and so
* would have to be extended to handle multiple FLASH parts on the same
* FlexSPI bus.
*/
priv = (FAR struct flexspi_nor_dev_s *)
kmm_zalloc(sizeof(struct flexspi_nor_dev_s));
if (priv)
{
/* Initialize the allocated structure (unsupported methods were
* nullified by kmm_zalloc).
*/
priv->mtd.erase = flexspi_nor_erase;
priv->mtd.bread = flexspi_nor_bread;
priv->mtd.bwrite = flexspi_nor_bwrite;
priv->mtd.read = flexspi_nor_read;
priv->mtd.ioctl = flexspi_nor_ioctl;
priv->mtd.name = "flexspi_nor";
priv->flexspi = flexspi;
priv->ahb_base = (uint8_t *) 0x60000000;
priv->port = FLEXSPI_PORT_A1;
ret = flexspi_nor_init(priv);
if (ret != OK)
{
/* Unrecognized! Discard all of that work we just did and
* return NULL
*/
ferr("ERROR Unrecognized FlexSPI NOR device\n");
goto errout_with_priv;
}
}
/* Return the implementation-specific state structure as the MTD device */
finfo("Return %p\n", priv);
return (FAR struct mtd_dev_s *)priv;
errout_with_priv:
kmm_free(priv);
return NULL;
}

View File

@ -91,7 +91,6 @@
****************************************************************************/
struct qspi_dev_s; /* Forward reference */
struct flexspi_dev_s; /* Forward reference */
/* The following defines the geometry for the device. It treats the device
* as though it were just an array of fixed size blocks. That is most likely
@ -595,18 +594,6 @@ FAR struct mtd_dev_s *n25qxxx_initialize(FAR struct qspi_dev_s *qspi,
FAR struct mtd_dev_s *w25qxxxjv_initialize(FAR struct qspi_dev_s *qspi,
bool unprotect);
/****************************************************************************
* Name: flexspi_nor_initialize
*
* Description:
* Create an initialized MTD device instance for the FlexSPI-based
* FLASH part.
*
****************************************************************************/
FAR struct mtd_dev_s *flexspi_nor_initialize(FAR struct flexspi_dev_s
*flexspi, bool unprotect);
/****************************************************************************
* Name: blockmtd_initialize
*

View File

@ -1,521 +0,0 @@
/****************************************************************************
* include/nuttx/spi/flexspi.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_SPI_FLEXSPI_H
#define __INCLUDE_NUTTX_SPI_FLEXSPI_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* LUT - LUT 0..LUT 63 */
#define FLEXSPI_LUT_OPERAND0_MASK (0xffU)
#define FLEXSPI_LUT_OPERAND0_SHIFT (0U)
/* OPERAND0 */
#define FLEXSPI_LUT_OPERAND0(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPERAND0_SHIFT)) & FLEXSPI_LUT_OPERAND0_MASK)
#define FLEXSPI_LUT_NUM_PADS0_MASK (0x300U)
#define FLEXSPI_LUT_NUM_PADS0_SHIFT (8U)
/* NUM_PADS0 */
#define FLEXSPI_LUT_NUM_PADS0(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_NUM_PADS0_SHIFT)) & FLEXSPI_LUT_NUM_PADS0_MASK)
#define FLEXSPI_LUT_OPCODE0_MASK (0xfc00U)
#define FLEXSPI_LUT_OPCODE0_SHIFT (10U)
/* OPCODE0 */
#define FLEXSPI_LUT_OPCODE0(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPCODE0_SHIFT)) & FLEXSPI_LUT_OPCODE0_MASK)
#define FLEXSPI_LUT_OPERAND1_MASK (0xff0000U)
#define FLEXSPI_LUT_OPERAND1_SHIFT (16U)
/* OPERAND1 */
#define FLEXSPI_LUT_OPERAND1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPERAND1_SHIFT)) & FLEXSPI_LUT_OPERAND1_MASK)
#define FLEXSPI_LUT_NUM_PADS1_MASK (0x3000000U)
#define FLEXSPI_LUT_NUM_PADS1_SHIFT (24U)
/* NUM_PADS1 - NUM_PADS1 */
#define FLEXSPI_LUT_NUM_PADS1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_NUM_PADS1_SHIFT)) & FLEXSPI_LUT_NUM_PADS1_MASK)
#define FLEXSPI_LUT_OPCODE1_MASK (0xfc000000U)
#define FLEXSPI_LUT_OPCODE1_SHIFT (26U)
/* OPCODE1 */
#define FLEXSPI_LUT_OPCODE1(x) (((uint32_t)(((uint32_t)(x)) << FLEXSPI_LUT_OPCODE1_SHIFT)) & FLEXSPI_LUT_OPCODE1_MASK)
/* Formula to form FLEXSPI instructions in LUT table */
#define FLEXSPI_LUT_SEQ(cmd0, pad0, op0, cmd1, pad1, op1) \
(FLEXSPI_LUT_OPERAND0(op0) | FLEXSPI_LUT_NUM_PADS0(pad0) | \
FLEXSPI_LUT_OPCODE0(cmd0) | FLEXSPI_LUT_OPERAND1(op1) | \
FLEXSPI_LUT_NUM_PADS1(pad1) | FLEXSPI_LUT_OPCODE1(cmd1))
/* Access macros ************************************************************/
/****************************************************************************
* Name: FLEXSPI_LOCK
*
* Description:
* On FlexSPI buses where there are multiple devices, it will be necessary
* to lock FlexSPI to have exclusive access to the buses for a sequence of
* transfers. The bus should be locked before the chip is selected.
*
* Input Parameters:
* dev - Device-specific state data
* lock - true: Lock FlexSPI bus, false: unlock FlexSPI bus
*
* Returned Value:
* None
*
****************************************************************************/
#define FLEXSPI_LOCK(d,l) (d)->ops->lock(d,l)
/****************************************************************************
* Name: FLEXSPI_TRANSFER
*
* Description:
* Perform one FlexSPI transfer
*
* Input Parameters:
* dev - Device-specific state data
* xfer - Describes the transfer to be performed.
*
* Returned Value:
* 0 on SUCCESS, STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT,
* STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR or
* STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT otherwise
*
****************************************************************************/
#define FLEXSPI_TRANSFER(d,x) (d)->ops->transfer_blocking(d,x)
/****************************************************************************
* Name: FLEXSPI_SOFTWARE_RESET
*
* Description:
* Perform FlexSPI software reset
*
* Input Parameters:
* dev - Device-specific state data
*
* Returned Value:
* none
*
****************************************************************************/
#define FLEXSPI_SOFTWARE_RESET(d) (d)->ops->software_reset(d)
/****************************************************************************
* Name: FLEXSPI_UPDATE_LUT
*
* Description:
* Perform FlexSPI LUT table update
*
* Input Parameters:
* dev - Device-specific state data
* index - Index start to update
* cmd - Command array
* count - Size of the array
*
* Returned Value:
* none
*
****************************************************************************/
#define FLEXSPI_UPDATE_LUT(d,i,c,n) (d)->ops->update_lut(d,i,c,n)
/****************************************************************************
* Name: FLEXSPI_SET_DEVICE_CONFIG
*
* Description:
* Perform FlexSPI device config
*
* Input Parameters:
* dev - Device-specific state data
* config - Config data for external device
* port - Port
*
* Returned Value:
* none
*
****************************************************************************/
#define FLEXSPI_SET_DEVICE_CONFIG(d,c,p) (d)->ops->set_device_config(d,c,p)
/****************************************************************************
* Public Types
****************************************************************************/
/* CMD definition of FLEXSPI, use to form LUT instruction, flexspi_command */
enum
{
FLEXSPI_COMMAND_STOP = 0x00, /* Stop execution, deassert CS */
FLEXSPI_COMMAND_SDR = 0x01, /* Transmit Command code to Flash,
* using SDR mode.
*/
FLEXSPI_COMMAND_RADDR_SDR = 0x02, /* Transmit Row Address to Flash,
* using SDR mode.
*/
FLEXSPI_COMMAND_CADDR_SDR = 0x03, /* Transmit Column Address to
* Flash, using SDR mode.
*/
FLEXSPI_COMMAND_MODE1_SDR = 0x04, /* Transmit 1-bit Mode bits to
* Flash, using SDR mode.
*/
FLEXSPI_COMMAND_MODE2_SDR = 0x05, /* Transmit 2-bit Mode bits to
* Flash, using SDR mode.
*/
FLEXSPI_COMMAND_MODE4_SDR = 0x06, /* Transmit 4-bit Mode bits to
* Flash, using SDR mode.
*/
FLEXSPI_COMMAND_MODE8_SDR = 0x07, /* Transmit 8-bit Mode bits to
* Flash, using SDR mode.
*/
FLEXSPI_COMMAND_WRITE_SDR = 0x08, /* Transmit Programming Data to
* Flash, using SDR mode.
*/
FLEXSPI_COMMAND_READ_SDR = 0x09, /* Receive Read Data from Flash,
* using SDR mode.
*/
FLEXSPI_COMMAND_LEARN_SDR = 0x0a, /* Receive Read Data or Preamble
* bit from Flash, SDR mode.
*/
FLEXSPI_COMMAND_DATSZ_SDR = 0x0b, /* Transmit Read/Program Data size
* (byte) to Flash, SDR mode.
*/
FLEXSPI_COMMAND_DUMMY_SDR = 0x0c, /* Leave data lines undriven by
* FlexSPI controller.
*/
FLEXSPI_COMMAND_DUMMY_RWDS_SDR = 0x0d, /* Leave data lines undriven by
* FlexSPI controller, dummy cycles
* decided by RWDS.
*/
FLEXSPI_COMMAND_DDR = 0x21, /* Transmit Command code to Flash,
* using DDR mode.
*/
FLEXSPI_COMMAND_RADDR_DDR = 0x22, /* Transmit Row Address to Flash,
* using DDR mode.
*/
FLEXSPI_COMMAND_CADDR_DDR = 0x23, /* Transmit Column Address to
* Flash, using DDR mode.
*/
FLEXSPI_COMMAND_MODE1_DDR = 0x24, /* Transmit 1-bit Mode bits to
* Flash, using DDR mode.
*/
FLEXSPI_COMMAND_MODE2_DDR = 0x25, /* Transmit 2-bit Mode bits to
* Flash, using DDR mode.
*/
FLEXSPI_COMMAND_MODE4_DDR = 0x26, /* Transmit 4-bit Mode bits to
* Flash, using DDR mode.
*/
FLEXSPI_COMMAND_MODE8_DDR = 0x27, /* Transmit 8-bit Mode bits to
* Flash, using DDR mode.
*/
FLEXSPI_COMMAND_WRITE_DDR = 0x28, /* Transmit Programming Data to
* Flash, using DDR mode.
*/
FLEXSPI_COMMAND_READ_DDR = 0x29, /* Receive Read Data from Flash,
* using DDR mode.
*/
FLEXSPI_COMMAND_LEARN_DDR = 0x2a, /* Receive Read Data or Preamble
* bit from Flash, DDR mode.
*/
FLEXSPI_COMMAND_DATSZ_DDR = 0x2b, /* Transmit Read/Program Data size
* (byte) to Flash, DDR mode.
*/
FLEXSPI_COMMAND_DUMMY_DDR = 0x2c, /* Leave data lines undriven by
* FlexSPI controller.
*/
FLEXSPI_COMMAND_DUMMY_RWDS_DDR = 0x2d, /* Leave data lines undriven by
* FlexSPI controller, dummy cycles
* decided by RWDS.
*/
FLEXSPI_COMMAND_JUMP_ON_CS = 0x1f, /* Stop execution, deassert CS and
* save operand[7:0] as the
* instruction start pointer for
* next sequence
*/
};
/* Pad definition of FLEXSPI, use to form LUT instruction */
enum flexspi_pad_e
{
FLEXSPI_1PAD = 0x00, /* Transmit command/address and transmit/receive data
* only through DATA0/DATA1.
*/
FLEXSPI_2PAD = 0x01, /* Transmit command/address and transmit/receive data
* only through DATA[1:0].
*/
FLEXSPI_4PAD = 0x02, /* Transmit command/address and transmit/receive data
* only through DATA[3:0].
*/
FLEXSPI_8PAD = 0x03, /* Transmit command/address and transmit/receive data
* only through DATA[7:0].
*/
};
/* FLEXSPI operation port select */
enum flexspi_port_e
{
FLEXSPI_PORT_A1 = 0x0, /* Access flash on A1 port */
FLEXSPI_PORT_A2, /* Access flash on A2 port */
FLEXSPI_PORT_B1, /* Access flash on B1 port */
FLEXSPI_PORT_B2, /* Access flash on B2 port */
FLEXSPI_PORT_COUNT
};
/* Command type */
enum flexspi_command_type_e
{
FLEXSPI_COMMAND, /* FlexSPI operation: Only command, both TX and Rx buffer
* are ignored.
*/
FLEXSPI_CONFIG, /* FlexSPI operation: Configure device mode, the TX fifo
* size is fixed in LUT.
*/
FLEXSPI_READ, /* FlexSPI operation: Read, only Rx Buffer is
* effective.
*/
FLEXSPI_WRITE, /* FlexSPI operation: Read, only Tx Buffer is
* effective.
*/
};
/* Status structure of FLEXSPI */
enum
{
STATUS_FLEXSPI_BUSY = 0, /* FLEXSPI is busy */
STATUS_FLEXSPI_SEQUENCE_EXECUTION_TIMEOUT = 1, /* Sequence execution
* timeout error occurred
* during FLEXSPI transfer.
*/
STATUS_FLEXSPI_IP_COMMAND_SEQUENCE_ERROR = 2, /* IP command Sequence
* execution timeout error
* occurred during FLEXSPI
* transfer.
*/
STATUS_FLEXSPI_IP_COMMAND_GRANT_TIMEOUT = 3, /* IP command grant timeout
* error occurred during
* FLEXSPI transfer.
*/
};
/* Transfer structure for FLEXSPI */
struct flexspi_transfer_s
{
uint32_t device_address; /* Operation device address */
enum flexspi_port_e port; /* Operation port */
enum flexspi_command_type_e cmd_type; /* Execution command type */
uint8_t seq_index; /* Sequence ID for command */
uint8_t seq_number; /* Sequence number for command */
uint32_t *data; /* Data buffer */
size_t data_size; /* Data size in bytes */
};
/* FLEXSPI interval unit for flash device select */
enum flexspi_cs_interval_cycle_unit_e
{
FLEXSPI_CS_INTERVAL_UNIT1_SCK_CYCLE = 0x0, /* Chip selection interval:
* CSINTERVAL * 1 serial
* clock cycle.
*/
FLEXSPI_CS_INTERVAL_UNIT256_SCK_CYCLE = 0x1, /* Chip selection interval:
* CSINTERVAL * 256 serial
* clock cycle.
*/
};
/* FLEXSPI AHB wait interval unit for writing */
enum flexspi_ahb_write_wait_unit_e
{
FLEXSPI_AHB_WRITE_WAIT_UNIT2_AHB_CYCLE = 0x0, /* AWRWAIT unit is 2
* ahb clock cycle.
*/
FLEXSPI_AHB_WRITE_WAIT_UNIT8_AHB_CYCLE = 0x1, /* AWRWAIT unit is 8
* ahb clock cycle.
*/
FLEXSPI_AHB_WRITE_WAIT_UNIT32_AHB_CYCLE = 0x2, /* AWRWAIT unit is 32
* ahb clock cycle.
*/
FLEXSPI_AHB_WRITE_WAIT_UNIT128_AHB_CYCLE = 0x3, /* AWRWAIT unit is 128
* ahb clock cycle.
*/
FLEXSPI_AHB_WRITE_WAIT_UNIT512_AHB_CYCLE = 0x4, /* AWRWAIT unit is 512
* ahb clock cycle.
*/
FLEXSPI_AHB_WRITE_WAIT_UNIT2048_AHB_CYCLE = 0x5, /* AWRWAIT unit is 2048
* ahb clock cycle.
*/
FLEXSPI_AHB_WRITE_WAIT_UNIT8192_AHB_CYCLE = 0x6, /* AWRWAIT unit is 8192
* ahb clock cycle.
*/
FLEXSPI_AHB_WRITE_WAIT_UNIT32768_AHB_CYCLE = 0x7, /* AWRWAIT unit is 32768
* ahb clock cycle.
*/
};
/* External device configuration items */
struct flexspi_device_config_s
{
uint32_t flexspi_root_clk; /* FLEXSPI serial root clock */
bool is_sck2_enabled; /* FLEXSPI use SCK2 */
uint32_t flash_size; /* Flash size in KByte */
enum flexspi_cs_interval_cycle_unit_e cs_interval_unit; /* CS interval unit, 1
* or 256 cycle.
*/
uint16_t cs_interval; /* CS line assert interval, multiply CS
* interval unit to get the CS line assert
* interval cycles.
*/
uint8_t cs_hold_time; /* CS line hold time */
uint8_t cs_setup_time; /* CS line setup time */
uint8_t data_valid_time; /* Data valid time for external device */
uint8_t columnspace; /* Column space size */
bool enable_word_address; /* If enable word address */
uint8_t awr_seq_index; /* Sequence ID for AHB write command */
uint8_t awr_seq_number; /* Sequence number for AHB write command */
uint8_t ard_seq_index; /* Sequence ID for AHB read command */
uint8_t ard_seq_number; /* Sequence number for AHB read command */
enum flexspi_ahb_write_wait_unit_e ahb_write_wait_unit; /* AHB write wait unit */
uint16_t ahb_write_wait_interval; /* AHB write wait interval, multiply AHB
* write interval unit to get the AHB
* write wait cycles.
*/
bool enable_write_mask; /* Enable/Disable FLEXSPI drive DQS pin as write mask
* when writing to external device.
*/
};
/* The FlexSPI vtable */
struct flexspi_dev_s;
struct flexspi_ops_s
{
CODE int (*lock)(FAR struct flexspi_dev_s *dev, bool lock);
CODE int (*transfer_blocking)(FAR struct flexspi_dev_s *dev,
FAR struct flexspi_transfer_s *xfer);
CODE void (*software_reset)(FAR struct flexspi_dev_s *dev);
CODE void (*update_lut)(FAR struct flexspi_dev_s *dev,
uint32_t index, const uint32_t *cmd,
uint32_t count);
CODE void (*set_device_config)(FAR struct flexspi_dev_s *dev,
FAR struct flexspi_device_config_s *config,
enum flexspi_port_e port);
};
/* FlexSPI private data. This structure only defines the initial fields of
* the structure visible to the FlexSPI client. The specific implementation
* may add additional, device specific fields
*/
struct flexspi_dev_s
{
FAR const struct flexspi_ops_s *ops;
};
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __INCLUDE_NUTTX_SPI_FLEXSPI_H */