drivers: flash: remove W25QXXDV driver
The spi_flash_w25qxxdv driver has been superseded by the generic spi_nor driver for over a year. The only non-refactoring change to the W25Q driver in the last 18 months was done to support a backport to 1.14. All devices supported by spi_flash_w25qxxdv driver are expected to be supported by the spi_nor driver, using the standard `jedec,spi-nor` devicetree compatible. No in-tree devicetree files make use of this driver. Remove the confusion about which driver to select by removing the unmaintained redundant driver. Signed-off-by: Peter Bigot <peter.bigot@nordicsemi.no>
This commit is contained in:
parent
27bf7c8010
commit
77aa89bcb5
10 changed files with 6 additions and 691 deletions
|
@ -197,6 +197,11 @@ Drivers and Sensors
|
||||||
|
|
||||||
* Flash
|
* Flash
|
||||||
|
|
||||||
|
* The driver selected by ``CONFIG_SPI_FLASH_W25QXXDV`` has been
|
||||||
|
removed as it is unmaintained and all its functionality is available
|
||||||
|
through ``CONFIG_SPI_NOR``. Out of tree uses should convert to the
|
||||||
|
supported driver using the ``jedec,spi-nor`` compatible.
|
||||||
|
|
||||||
|
|
||||||
* GPIO
|
* GPIO
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ zephyr_library_sources_ifdef(CONFIG_SPI_NOR spi_nor.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_NORDIC_QSPI_NOR nrf_qspi_nor.c)
|
zephyr_library_sources_ifdef(CONFIG_NORDIC_QSPI_NOR nrf_qspi_nor.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_FLASH_SIMULATOR flash_simulator.c)
|
zephyr_library_sources_ifdef(CONFIG_FLASH_SIMULATOR flash_simulator.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_SPI_FLASH_AT45 spi_flash_at45.c)
|
zephyr_library_sources_ifdef(CONFIG_SPI_FLASH_AT45 spi_flash_at45.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_SPI_FLASH_W25QXXDV spi_flash_w25qxxdv.c)
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF soc_flash_nrf.c)
|
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NRF soc_flash_nrf.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_MCUX soc_flash_mcux.c)
|
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_MCUX soc_flash_mcux.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_FLASH_PAGE_LAYOUT flash_page_layout.c)
|
zephyr_library_sources_ifdef(CONFIG_FLASH_PAGE_LAYOUT flash_page_layout.c)
|
||||||
|
|
|
@ -76,8 +76,6 @@ source "drivers/flash/Kconfig.sam0"
|
||||||
|
|
||||||
source "drivers/flash/Kconfig.sam"
|
source "drivers/flash/Kconfig.sam"
|
||||||
|
|
||||||
source "drivers/flash/Kconfig.w25qxxdv"
|
|
||||||
|
|
||||||
source "drivers/flash/Kconfig.simulator"
|
source "drivers/flash/Kconfig.simulator"
|
||||||
|
|
||||||
source "drivers/flash/Kconfig.rv32m1"
|
source "drivers/flash/Kconfig.rv32m1"
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
# Copyright (c) 2018 Intel Corporation
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
menuconfig SPI_FLASH_W25QXXDV
|
|
||||||
bool "SPI NOR Flash Winbond W25QXXDV"
|
|
||||||
select FLASH_HAS_DRIVER_ENABLED
|
|
||||||
depends on SPI
|
|
||||||
|
|
||||||
if SPI_FLASH_W25QXXDV
|
|
||||||
|
|
||||||
config SPI_FLASH_W25QXXDV_DRV_NAME
|
|
||||||
string "SPI flash device name"
|
|
||||||
default "W25QXXDV"
|
|
||||||
|
|
||||||
config SPI_FLASH_W25QXXDV_INIT_PRIORITY
|
|
||||||
int
|
|
||||||
default 80
|
|
||||||
help
|
|
||||||
Device driver initialization priority.
|
|
||||||
Device is connected to SPI bus, it has to
|
|
||||||
be initialized after SPI driver.
|
|
||||||
|
|
||||||
config SPI_FLASH_W25QXXDV_GPIO_CS_WAIT_DELAY
|
|
||||||
int "Delay time in us"
|
|
||||||
default 0
|
|
||||||
help
|
|
||||||
This is the wait delay (in us) to allow for CS switching to take effect
|
|
||||||
|
|
||||||
config SPI_FLASH_W25QXXDV_FLASH_SIZE
|
|
||||||
int "Flash size in bytes"
|
|
||||||
default 2097152
|
|
||||||
help
|
|
||||||
This is the flash capacity in bytes.
|
|
||||||
|
|
||||||
config SPI_FLASH_W25QXXDV_DEVICE_ID
|
|
||||||
hex "Device ID in hex"
|
|
||||||
default 0x00ef4015
|
|
||||||
help
|
|
||||||
This is the device ID of the flash chip to use, which is 0x00ef4015 for
|
|
||||||
the W25QXXDV
|
|
||||||
|
|
||||||
config SPI_FLASH_W25QXXDV_PAGE_PROGRAM_SIZE
|
|
||||||
int "Page Program Size in bytes"
|
|
||||||
default 256
|
|
||||||
help
|
|
||||||
This is the maximum size of a page program operation. Writing data
|
|
||||||
over this page boundary will split the write operation into two
|
|
||||||
pages.
|
|
||||||
|
|
||||||
endif # SPI_FLASH_W25QXXDV
|
|
|
@ -1,470 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define DT_DRV_COMPAT winbond_w25q16
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#include <drivers/flash.h>
|
|
||||||
#include <drivers/spi.h>
|
|
||||||
#include <init.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "spi_flash_w25qxxdv_defs.h"
|
|
||||||
#include "spi_flash_w25qxxdv.h"
|
|
||||||
#include "flash_priv.h"
|
|
||||||
|
|
||||||
#if defined(CONFIG_MULTITHREADING)
|
|
||||||
#define SYNC_INIT() k_sem_init( \
|
|
||||||
&((struct spi_flash_data *)dev->data)->sem, 1, UINT_MAX)
|
|
||||||
#define SYNC_LOCK() k_sem_take(&driver_data->sem, K_FOREVER)
|
|
||||||
#define SYNC_UNLOCK() k_sem_give(&driver_data->sem)
|
|
||||||
#else
|
|
||||||
#define SYNC_INIT()
|
|
||||||
#define SYNC_LOCK()
|
|
||||||
#define SYNC_UNLOCK()
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const struct flash_parameters flash_wb_parameters = {
|
|
||||||
.write_block_size = 1,
|
|
||||||
.erase_value = 0xff,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int spi_flash_wb_access(struct spi_flash_data *ctx,
|
|
||||||
uint8_t cmd, bool addressed, off_t offset,
|
|
||||||
void *data, size_t length, bool write)
|
|
||||||
{
|
|
||||||
uint8_t access[4];
|
|
||||||
struct spi_buf buf[2] = {
|
|
||||||
{
|
|
||||||
.buf = access
|
|
||||||
},
|
|
||||||
{
|
|
||||||
.buf = data,
|
|
||||||
.len = length
|
|
||||||
}
|
|
||||||
};
|
|
||||||
struct spi_buf_set tx = {
|
|
||||||
.buffers = buf,
|
|
||||||
};
|
|
||||||
|
|
||||||
access[0] = cmd;
|
|
||||||
|
|
||||||
if (addressed) {
|
|
||||||
access[1] = (uint8_t) (offset >> 16);
|
|
||||||
access[2] = (uint8_t) (offset >> 8);
|
|
||||||
access[3] = (uint8_t) offset;
|
|
||||||
|
|
||||||
buf[0].len = 4;
|
|
||||||
} else {
|
|
||||||
buf[0].len = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.count = length ? 2 : 1;
|
|
||||||
|
|
||||||
if (!write) {
|
|
||||||
const struct spi_buf_set rx = {
|
|
||||||
.buffers = buf,
|
|
||||||
.count = 2
|
|
||||||
};
|
|
||||||
|
|
||||||
return spi_transceive(ctx->spi, &ctx->spi_cfg, &tx, &rx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return spi_write(ctx->spi, &ctx->spi_cfg, &tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int spi_flash_wb_id(struct device *dev)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
uint32_t temp_data;
|
|
||||||
uint8_t buf[3];
|
|
||||||
|
|
||||||
if (spi_flash_wb_access(driver_data, W25QXXDV_CMD_RDID,
|
|
||||||
false, 0, buf, 3, false) != 0) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_data = ((uint32_t) buf[0]) << 16;
|
|
||||||
temp_data |= ((uint32_t) buf[1]) << 8;
|
|
||||||
temp_data |= (uint32_t) buf[2];
|
|
||||||
|
|
||||||
if (temp_data != CONFIG_SPI_FLASH_W25QXXDV_DEVICE_ID) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t spi_flash_wb_reg_read(struct device *dev, uint8_t reg)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
|
|
||||||
if (spi_flash_wb_access(driver_data, reg,
|
|
||||||
false, 0, ®, 1, false)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void wait_for_flash_idle(struct device *dev)
|
|
||||||
{
|
|
||||||
uint8_t reg;
|
|
||||||
|
|
||||||
do {
|
|
||||||
reg = spi_flash_wb_reg_read(dev, W25QXXDV_CMD_RDSR);
|
|
||||||
} while (reg & W25QXXDV_WIP_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_wb_reg_write(struct device *dev, uint8_t reg)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
|
|
||||||
if (spi_flash_wb_access(driver_data, reg, false, 0,
|
|
||||||
NULL, 0, true) != 0) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_wb_read(struct device *dev, off_t offset, void *data,
|
|
||||||
size_t len)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (offset < 0) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYNC_LOCK();
|
|
||||||
|
|
||||||
wait_for_flash_idle(dev);
|
|
||||||
|
|
||||||
ret = spi_flash_wb_access(driver_data, W25QXXDV_CMD_READ,
|
|
||||||
true, offset, data, len, false);
|
|
||||||
|
|
||||||
SYNC_UNLOCK();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_wb_write_protection_set_with_lock(struct device *dev,
|
|
||||||
bool enable, bool lock)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
uint8_t reg = 0U;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (lock) {
|
|
||||||
SYNC_LOCK();
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_flash_idle(dev);
|
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
reg = W25QXXDV_CMD_WRDI;
|
|
||||||
} else {
|
|
||||||
reg = W25QXXDV_CMD_WREN;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = spi_flash_wb_reg_write(dev, reg);
|
|
||||||
|
|
||||||
if (lock) {
|
|
||||||
SYNC_UNLOCK();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_wb_write_protection_set(struct device *dev, bool enable)
|
|
||||||
{
|
|
||||||
return spi_flash_wb_write_protection_set_with_lock(dev, enable, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_wb_program_page(struct device *dev, off_t offset,
|
|
||||||
const void *data, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t reg;
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
|
|
||||||
__ASSERT(len <= CONFIG_SPI_FLASH_W25QXXDV_PAGE_PROGRAM_SIZE,
|
|
||||||
"Maximum length is %d for page programming (actual:%d)",
|
|
||||||
CONFIG_SPI_FLASH_W25QXXDV_PAGE_PROGRAM_SIZE, len);
|
|
||||||
|
|
||||||
wait_for_flash_idle(dev);
|
|
||||||
|
|
||||||
reg = spi_flash_wb_reg_read(dev, W25QXXDV_CMD_RDSR);
|
|
||||||
if (!(reg & W25QXXDV_WEL_BIT)) {
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_flash_idle(dev);
|
|
||||||
|
|
||||||
/* Assume write protection has been disabled. Note that w25qxxdv
|
|
||||||
* flash automatically turns on write protection at the completion
|
|
||||||
* of each write or erase transaction.
|
|
||||||
*/
|
|
||||||
return spi_flash_wb_access(driver_data, W25QXXDV_CMD_PP,
|
|
||||||
true, offset, (void *)data, len, true);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_wb_write(struct device *dev, off_t offset,
|
|
||||||
const void *data, size_t len)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
off_t page_offset;
|
|
||||||
/* Cast `data` to prevent `void*` arithmetic */
|
|
||||||
const uint8_t *data_ptr = data;
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
|
|
||||||
if (offset < 0) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYNC_LOCK();
|
|
||||||
|
|
||||||
/* Calculate the offset in the first page we write */
|
|
||||||
page_offset = offset % CONFIG_SPI_FLASH_W25QXXDV_PAGE_PROGRAM_SIZE;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Write all data that does not fit into a single programmable page.
|
|
||||||
* By doing this logic, we can safely disable lock protection in
|
|
||||||
* between pages as in case the user did not disable protection then
|
|
||||||
* it will fail on the first write.
|
|
||||||
*/
|
|
||||||
while ((page_offset + len) >
|
|
||||||
CONFIG_SPI_FLASH_W25QXXDV_PAGE_PROGRAM_SIZE) {
|
|
||||||
size_t len_to_write_in_page =
|
|
||||||
CONFIG_SPI_FLASH_W25QXXDV_PAGE_PROGRAM_SIZE -
|
|
||||||
page_offset;
|
|
||||||
|
|
||||||
ret = spi_flash_wb_program_page(dev, offset,
|
|
||||||
data_ptr, len_to_write_in_page);
|
|
||||||
if (ret) {
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = spi_flash_wb_write_protection_set_with_lock(dev,
|
|
||||||
false, false);
|
|
||||||
if (ret) {
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
len -= len_to_write_in_page;
|
|
||||||
offset += len_to_write_in_page;
|
|
||||||
data_ptr += len_to_write_in_page;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For the subsequent pages we always start at the beginning
|
|
||||||
* of a page
|
|
||||||
*/
|
|
||||||
page_offset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = spi_flash_wb_program_page(dev, offset, data_ptr, len);
|
|
||||||
|
|
||||||
end:
|
|
||||||
SYNC_UNLOCK();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int spi_flash_wb_erase_internal(struct device *dev,
|
|
||||||
off_t offset, size_t size)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
bool need_offset = true;
|
|
||||||
uint8_t erase_opcode;
|
|
||||||
|
|
||||||
if (offset < 0) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
wait_for_flash_idle(dev);
|
|
||||||
|
|
||||||
/* write enable */
|
|
||||||
spi_flash_wb_reg_write(dev, W25QXXDV_CMD_WREN);
|
|
||||||
|
|
||||||
wait_for_flash_idle(dev);
|
|
||||||
|
|
||||||
switch (size) {
|
|
||||||
case W25QXXDV_SECTOR_SIZE:
|
|
||||||
erase_opcode = W25QXXDV_CMD_SE;
|
|
||||||
break;
|
|
||||||
case W25QXXDV_BLOCK32K_SIZE:
|
|
||||||
erase_opcode = W25QXXDV_CMD_BE32K;
|
|
||||||
break;
|
|
||||||
case W25QXXDV_BLOCK_SIZE:
|
|
||||||
erase_opcode = W25QXXDV_CMD_BE;
|
|
||||||
break;
|
|
||||||
case CONFIG_SPI_FLASH_W25QXXDV_FLASH_SIZE:
|
|
||||||
erase_opcode = W25QXXDV_CMD_CE;
|
|
||||||
need_offset = false;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Assume write protection has been disabled. Note that w25qxxdv
|
|
||||||
* flash automatically turns on write protection at the completion
|
|
||||||
* of each write or erase transaction.
|
|
||||||
*/
|
|
||||||
return spi_flash_wb_access(driver_data, erase_opcode,
|
|
||||||
need_offset, offset, NULL, 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_wb_erase(struct device *dev, off_t offset, size_t size)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *const driver_data = dev->data;
|
|
||||||
int ret = 0;
|
|
||||||
uint32_t new_offset = offset;
|
|
||||||
uint32_t size_remaining = size;
|
|
||||||
uint8_t reg;
|
|
||||||
|
|
||||||
if ((offset < 0) || ((offset & W25QXXDV_SECTOR_MASK) != 0) ||
|
|
||||||
((size + offset) > CONFIG_SPI_FLASH_W25QXXDV_FLASH_SIZE) ||
|
|
||||||
((size & W25QXXDV_SECTOR_MASK) != 0)) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
SYNC_LOCK();
|
|
||||||
|
|
||||||
reg = spi_flash_wb_reg_read(dev, W25QXXDV_CMD_RDSR);
|
|
||||||
|
|
||||||
if (!(reg & W25QXXDV_WEL_BIT)) {
|
|
||||||
SYNC_UNLOCK();
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((size_remaining >= W25QXXDV_SECTOR_SIZE) && (ret == 0)) {
|
|
||||||
if (size_remaining == CONFIG_SPI_FLASH_W25QXXDV_FLASH_SIZE) {
|
|
||||||
ret = spi_flash_wb_erase_internal(dev, offset, size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size_remaining >= W25QXXDV_BLOCK_SIZE) &&
|
|
||||||
((new_offset & (W25QXXDV_BLOCK_SIZE - 1)) == 0)) {
|
|
||||||
ret = spi_flash_wb_erase_internal(dev, new_offset,
|
|
||||||
W25QXXDV_BLOCK_SIZE);
|
|
||||||
new_offset += W25QXXDV_BLOCK_SIZE;
|
|
||||||
size_remaining -= W25QXXDV_BLOCK_SIZE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((size_remaining >= W25QXXDV_BLOCK32K_SIZE) &&
|
|
||||||
((new_offset & (W25QXXDV_BLOCK32K_SIZE - 1)) == 0)) {
|
|
||||||
ret = spi_flash_wb_erase_internal(dev, new_offset,
|
|
||||||
W25QXXDV_BLOCK32K_SIZE);
|
|
||||||
new_offset += W25QXXDV_BLOCK32K_SIZE;
|
|
||||||
size_remaining -= W25QXXDV_BLOCK32K_SIZE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size_remaining >= W25QXXDV_SECTOR_SIZE) {
|
|
||||||
ret = spi_flash_wb_erase_internal(dev, new_offset,
|
|
||||||
W25QXXDV_SECTOR_SIZE);
|
|
||||||
new_offset += W25QXXDV_SECTOR_SIZE;
|
|
||||||
size_remaining -= W25QXXDV_SECTOR_SIZE;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SYNC_UNLOCK();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
|
|
||||||
static struct flash_pages_layout dev_layout;
|
|
||||||
|
|
||||||
static void flash_wb_pages_layout(struct device *dev,
|
|
||||||
const struct flash_pages_layout **layout,
|
|
||||||
size_t *layout_size)
|
|
||||||
{
|
|
||||||
*layout = &dev_layout;
|
|
||||||
*layout_size = 1;
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
|
|
||||||
|
|
||||||
static const struct flash_parameters *
|
|
||||||
flash_wb_get_parameters(const struct device *dev)
|
|
||||||
{
|
|
||||||
ARG_UNUSED(dev);
|
|
||||||
|
|
||||||
return &flash_wb_parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct flash_driver_api spi_flash_api = {
|
|
||||||
.read = spi_flash_wb_read,
|
|
||||||
.write = spi_flash_wb_write,
|
|
||||||
.erase = spi_flash_wb_erase,
|
|
||||||
.write_protection = spi_flash_wb_write_protection_set,
|
|
||||||
.get_parameters = flash_wb_get_parameters,
|
|
||||||
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
|
|
||||||
.page_layout = flash_wb_pages_layout,
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
static int spi_flash_wb_configure(struct device *dev)
|
|
||||||
{
|
|
||||||
struct spi_flash_data *data = dev->data;
|
|
||||||
|
|
||||||
data->spi = device_get_binding(DT_INST_BUS_LABEL(0));
|
|
||||||
if (!data->spi) {
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->spi_cfg.frequency = DT_INST_PROP(0, spi_max_frequency);
|
|
||||||
data->spi_cfg.operation = SPI_WORD_SET(8);
|
|
||||||
data->spi_cfg.slave = DT_INST_REG_ADDR(0);
|
|
||||||
|
|
||||||
#if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
|
|
||||||
data->cs_ctrl.gpio_dev = device_get_binding(
|
|
||||||
DT_INST_SPI_DEV_CS_GPIOS_LABEL(0));
|
|
||||||
if (!data->cs_ctrl.gpio_dev) {
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
data->cs_ctrl.gpio_pin = DT_INST_SPI_DEV_CS_GPIOS_PIN(0);
|
|
||||||
data->cs_ctrl.gpio_dt_flags = DT_INST_SPI_DEV_CS_GPIOS_FLAGS(0);
|
|
||||||
data->cs_ctrl.delay = CONFIG_SPI_FLASH_W25QXXDV_GPIO_CS_WAIT_DELAY;
|
|
||||||
|
|
||||||
data->spi_cfg.cs = &data->cs_ctrl;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return spi_flash_wb_id(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int spi_flash_init(struct device *dev)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
SYNC_INIT();
|
|
||||||
|
|
||||||
ret = spi_flash_wb_configure(dev);
|
|
||||||
|
|
||||||
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
|
|
||||||
/*
|
|
||||||
* Note: we use the sector size rather than the page size as some
|
|
||||||
* modules that consumes the flash page layout assume the page
|
|
||||||
* size is the minimal size they can erase.
|
|
||||||
*/
|
|
||||||
dev_layout.pages_count = (CONFIG_SPI_FLASH_W25QXXDV_FLASH_SIZE / W25QXXDV_SECTOR_SIZE);
|
|
||||||
dev_layout.pages_size = W25QXXDV_SECTOR_SIZE;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct spi_flash_data spi_flash_memory_data;
|
|
||||||
|
|
||||||
DEVICE_AND_API_INIT(spi_flash_memory, CONFIG_SPI_FLASH_W25QXXDV_DRV_NAME,
|
|
||||||
spi_flash_init, &spi_flash_memory_data, NULL, POST_KERNEL,
|
|
||||||
CONFIG_SPI_FLASH_W25QXXDV_INIT_PRIORITY, &spi_flash_api);
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* @brief This file defines the private data structures for spi flash driver
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ZEPHYR_DRIVERS_FLASH_SPI_FLASH_W25QXXDV_H_
|
|
||||||
#define ZEPHYR_DRIVERS_FLASH_SPI_FLASH_W25QXXDV_H_
|
|
||||||
|
|
||||||
#define DT_DRV_COMPAT winbond_w25q16
|
|
||||||
|
|
||||||
struct spi_flash_data {
|
|
||||||
struct device *spi;
|
|
||||||
#if DT_INST_SPI_DEV_HAS_CS_GPIOS(0)
|
|
||||||
struct spi_cs_control cs_ctrl;
|
|
||||||
#endif
|
|
||||||
struct spi_config spi_cfg;
|
|
||||||
#if defined(CONFIG_MULTITHREADING)
|
|
||||||
struct k_sem sem;
|
|
||||||
#endif /* CONFIG_MULTITHREADING */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* ZEPHYR_DRIVERS_FLASH_SPI_FLASH_W25QXXDV_H_ */
|
|
|
@ -1,118 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2016 Intel Corporation.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* @brief This file has the WinBond SPI flash private definitions
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef ZEPHYR_DRIVERS_FLASH_SPI_FLASH_W25QXXDV_DEFS_H_
|
|
||||||
#define ZEPHYR_DRIVERS_FLASH_SPI_FLASH_W25QXXDV_DEFS_H_
|
|
||||||
|
|
||||||
/* Status Registers
|
|
||||||
* S7 S6 S5 S4 S3 S2 S1 S0
|
|
||||||
* +-------------------------------------------------------+
|
|
||||||
* | SRP0 | SEC | TB | BP2 | BP1 | BP0 | WEL | BUSY |
|
|
||||||
* +-------------------------------------------------------+
|
|
||||||
*
|
|
||||||
* BUSY - Erase/Write In Progress - 1 device is executing a command, 0 ready for command
|
|
||||||
* WEL - Write Enable Latch - 1 write enable is received, 0 completion of
|
|
||||||
* a Write Disable, Page Program, Erase, Write Status Register
|
|
||||||
*
|
|
||||||
* S15 S14 S13 S12 S11 S10 S9 S8
|
|
||||||
* +-------------------------------------------------------+
|
|
||||||
* | SUS | CMP | LB3 | LB2 | LB1 | xxx | QE | SRP1 |
|
|
||||||
* +-------------------------------------------------------+
|
|
||||||
*
|
|
||||||
* S23 S22 S21 S20 S19 S18 S17 S16
|
|
||||||
* +----------------------------------------------------------+
|
|
||||||
* | HOLD/RST | DRV1 | DRV0 | xxx | xxx | WPS | xxx | xxx |
|
|
||||||
* +----------------------------------------------------------+
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define W25QXXDV_RDID_VALUE (0x00ef4015)
|
|
||||||
#define W25QXXDV_MAX_LEN_REG_CMD (6)
|
|
||||||
#define W25QXXDV_OPCODE_LEN (1)
|
|
||||||
#define W25QXXDV_ADDRESS_WIDTH (3)
|
|
||||||
#define W25QXXDV_LEN_CMD_ADDRESS (4)
|
|
||||||
#define W25QXXDV_LEN_CMD_AND_ID (4)
|
|
||||||
|
|
||||||
/* relevant status register bits */
|
|
||||||
#define W25QXXDV_WIP_BIT (0x1 << 0)
|
|
||||||
#define W25QXXDV_WEL_BIT (0x1 << 1)
|
|
||||||
#define W25QXXDV_SRWD_BIT (0x1 << 7)
|
|
||||||
#define W25QXXDV_TB_BIT (0x1 << 3)
|
|
||||||
#define W25QXXDV_SR_BP_OFFSET (2)
|
|
||||||
|
|
||||||
/* relevant security register bits */
|
|
||||||
#define W25QXXDV_SECR_WPSEL_BIT (0x1 << 7)
|
|
||||||
#define W25QXXDV_SECR_EFAIL_BIT (0x1 << 6)
|
|
||||||
#define W25QXXDV_SECR_PFAIL_BIT (0x1 << 5)
|
|
||||||
|
|
||||||
/* supported erase size */
|
|
||||||
#define W25QXXDV_SECTOR_SIZE (0x1000)
|
|
||||||
#define W25QXXDV_BLOCK32K_SIZE (0x8000)
|
|
||||||
#define W25QXXDV_BLOCK_SIZE (0x10000)
|
|
||||||
|
|
||||||
#define W25QXXDV_SECTOR_MASK (0xFFF)
|
|
||||||
|
|
||||||
/* ID commands */
|
|
||||||
#define W25QXXDV_CMD_RDID 0x9F
|
|
||||||
#define W25QXXDV_CMD_RES 0xAB
|
|
||||||
#define W25QXXDV_CMD_REMS 0x90
|
|
||||||
#define W25QXXDV_CMD_QPIID 0xAF
|
|
||||||
#define W25QXXDV_CMD_UNID 0x4B
|
|
||||||
|
|
||||||
/*Register commands */
|
|
||||||
#define W25QXXDV_CMD_WRSR 0x01
|
|
||||||
#define W25QXXDV_CMD_RDSR 0x05
|
|
||||||
#define W25QXXDV_CMD_RDSR2 0x35
|
|
||||||
#define W25QXXDV_CMD_WRSCUR 0x2F
|
|
||||||
#define W25QXXDV_CMD_RDSCUR 0x48
|
|
||||||
|
|
||||||
/* READ commands */
|
|
||||||
#define W25QXXDV_CMD_READ 0x03
|
|
||||||
#define W25QXXDV_CMD_2READ 0xBB
|
|
||||||
#define W25QXXDV_CMD_4READ 0xEB
|
|
||||||
#define W25QXXDV_CMD_FASTREAD 0x0B
|
|
||||||
#define W25QXXDV_CMD_DREAD 0x3B
|
|
||||||
#define W25QXXDV_CMD_QREAD 0x6B
|
|
||||||
#define W25QXXDV_CMD_RDSFDP 0x5A
|
|
||||||
|
|
||||||
/* Program commands */
|
|
||||||
#define W25QXXDV_CMD_WREN 0x06
|
|
||||||
#define W25QXXDV_CMD_WRDI 0x04
|
|
||||||
#define W25QXXDV_CMD_PP 0x02
|
|
||||||
#define W25QXXDV_CMD_4PP 0x32
|
|
||||||
#define W25QXXDV_CMD_WRENVSR 0x50
|
|
||||||
|
|
||||||
/* Erase commands */
|
|
||||||
#define W25QXXDV_CMD_SE 0x20
|
|
||||||
#define W25QXXDV_CMD_BE32K 0x52
|
|
||||||
#define W25QXXDV_CMD_BE 0xD8
|
|
||||||
#define W25QXXDV_CMD_CE 0x60
|
|
||||||
|
|
||||||
/* Mode setting commands */
|
|
||||||
#define W25QXXDV_CMD_DP 0xB9
|
|
||||||
#define W25QXXDV_CMD_RDP 0xAB
|
|
||||||
|
|
||||||
/* Reset commands */
|
|
||||||
#define W25QXXDV_CMD_RSTEN 0x66
|
|
||||||
#define W25QXXDV_CMD_RST 0x99
|
|
||||||
#define W25QXXDV_CMD_RSTQIO 0xF5
|
|
||||||
|
|
||||||
/* Security commands */
|
|
||||||
#define W25QXXDV_CMD_ERSR 0x44
|
|
||||||
#define W25QXXDV_CMD_PRSR 0x42
|
|
||||||
|
|
||||||
/* Suspend/Resume commands */
|
|
||||||
#define W25QXXDV_CMD_PGM_ERS_S 0x75
|
|
||||||
#define W25QXXDV_CMD_PGM_ERS_R 0x7A
|
|
||||||
|
|
||||||
#define W25QXXDV_CMD_NOP 0x00
|
|
||||||
|
|
||||||
#endif /*ZEPHYR_DRIVERS_FLASH_SPI_FLASH_W25QXXDV_DEFS_H_*/
|
|
|
@ -1,8 +0,0 @@
|
||||||
# Copyright (c) 2018, Linaro Limited
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
description: SPI slave NOR FLASH
|
|
||||||
|
|
||||||
compatible: "winbond,w25q16"
|
|
||||||
|
|
||||||
include: spi-device.yaml
|
|
|
@ -11,11 +11,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if (CONFIG_SPI_FLASH_W25QXXDV - 0)
|
#if (CONFIG_SPI_NOR - 0) || \
|
||||||
/* NB: W25Q16DV is a JEDEC spi-nor device, but has a separate driver. */
|
|
||||||
#define FLASH_DEVICE CONFIG_SPI_FLASH_W25QXXDV_DRV_NAME
|
|
||||||
#define FLASH_NAME "W25QXXDV"
|
|
||||||
#elif (CONFIG_SPI_NOR - 0) || \
|
|
||||||
DT_NODE_HAS_STATUS(DT_INST(0, jedec_spi_nor), okay)
|
DT_NODE_HAS_STATUS(DT_INST(0, jedec_spi_nor), okay)
|
||||||
#define FLASH_DEVICE DT_LABEL(DT_INST(0, jedec_spi_nor))
|
#define FLASH_DEVICE DT_LABEL(DT_INST(0, jedec_spi_nor))
|
||||||
#define FLASH_NAME "JEDEC SPI-NOR"
|
#define FLASH_NAME "JEDEC SPI-NOR"
|
||||||
|
|
|
@ -449,13 +449,6 @@ test_spi_lmp90100: lmp90100@2c {
|
||||||
#io-channel-cells = <2>;
|
#io-channel-cells = <2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
test_spi_w25q16: w25q16@2d {
|
|
||||||
compatible = "winbond,w25q16";
|
|
||||||
label = "W25Q16";
|
|
||||||
reg = <0x2d>;
|
|
||||||
spi-max-frequency = <0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
test_spi_ws2812_spi: ws2812-spi@2e {
|
test_spi_ws2812_spi: ws2812-spi@2e {
|
||||||
compatible = "worldsemi,ws2812-spi";
|
compatible = "worldsemi,ws2812-spi";
|
||||||
label = "WS2812-SPI";
|
label = "WS2812-SPI";
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue