Skip to content
Permalink
Browse files

drivers/spi_nor: remove configurability of page/sector/block sizes

The JEDEC API defines the hardware page, sector, and block sizes.
Deprecate the Kconfig settings, remove the `erase-size-block` property,
and add `has-be32k` to indicate that 32K-byte erase is supported.
Rework the driver to use the constants instead of configured values.

Signed-off-by: Peter A. Bigot <pab@pabigot.com>
  • Loading branch information...
pabigot authored and galak committed Jul 20, 2019
1 parent 4fc2445 commit 2a590d3fa5e2b15b88df70a17cd6d2d630a2c933
@@ -183,6 +183,7 @@ arduino_i2c: &i2c0 {
label = "MX25R64";
jedec-id = <0xc2 0x28 0x17>;
size = <67108864>;
has-be32k;
wp-gpios = <&gpio0 22 0>;
hold-gpios = <&gpio0 23 0>;
};
@@ -174,12 +174,6 @@ config SPI
config SPI_NOR
default y

config SPI_NOR_PAGE_SIZE
default 256

config SPI_NOR_SECTOR_SIZE
default 4096

config FLASH_HAS_PAGE_LAYOUT
default y

@@ -55,7 +55,6 @@
label = "MX25UM512";
jedec-id = <0xc2 0x80 0x3a>;
size = <0x2000000>;
erase-block-size = <0x10000>;
write-block-size = <1>;
};
};
@@ -30,12 +30,14 @@ config SPI_NOR_PAGE_SIZE
int "Page size of SPI flash"
default 0
help
This option specifies page size of SPI flash
Note: This option is deprecated and is ignored. Page size is
always 256.

config SPI_NOR_SECTOR_SIZE
int "Sector size of SPI flash"
default 0
help
This option specifies sector size of SPI flash
Note: This option is deprecated and is ignored. Sector size
is always 4096.

endif # SPI_NOR
@@ -14,28 +14,7 @@
#include "spi_nor.h"
#include "flash_priv.h"

#define SZ_256 0x100
#define SZ_512 0x200
#define SZ_1024 0x400
#define SZ_4K 0x1000
#define SZ_32K 0x8000
#define SZ_64K 0x10000

#define MASK_256 0xFF
#define MASK_4K 0xFFF
#define MASK_32K 0x7FFF
#define MASK_64K 0xFFFF

#define SPI_NOR_MAX_ADDR_WIDTH 4
#define SECTORS_COUNT ((DT_INST_0_JEDEC_SPI_NOR_SIZE / 8) \
/ CONFIG_SPI_NOR_SECTOR_SIZE)

#define JEDEC_ID(x) \
{ \
((x) >> 16) & 0xFF, \
((x) >> 8) & 0xFF, \
(x) & 0xFF, \
}

/**
* struct spi_nor_data - Structure for defining the SPI NOR access
@@ -178,8 +157,7 @@ static int spi_nor_read(struct device *dev, off_t addr, void *dest,
int to_read;

/* should be between 0 and flash size */
if ((addr < 0) || (addr + size) > (params->sector_size
* params->n_sectors)) {
if ((addr < 0) || ((addr + size) > params->size)) {
return -EINVAL;
}

@@ -189,8 +167,8 @@ static int spi_nor_read(struct device *dev, off_t addr, void *dest,

while (size) {
to_read = size;
if (size > params->page_size) {
to_read = params->page_size;
if (size > SPI_NOR_PAGE_SIZE) {
to_read = SPI_NOR_PAGE_SIZE;
}

ret = spi_nor_cmd_addr_read(dev, SPI_NOR_CMD_READ, addr,
@@ -218,8 +196,7 @@ static int spi_nor_write(struct device *dev, off_t addr, const void *src,
size_t to_write;

/* should be between 0 and flash size */
if ((addr < 0) || ((size + addr) > (params->sector_size *
params->n_sectors))) {
if ((addr < 0) || ((size + addr) > params->size)) {
return -EINVAL;
}

@@ -230,8 +207,8 @@ static int spi_nor_write(struct device *dev, off_t addr, const void *src,
spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN);

to_write = size;
if (size >= params->page_size) {
to_write = params->page_size;
if (size >= SPI_NOR_PAGE_SIZE) {
to_write = SPI_NOR_PAGE_SIZE;
}

ret = spi_nor_cmd_addr_write(dev, SPI_NOR_CMD_PP, addr,
@@ -258,8 +235,7 @@ static int spi_nor_erase(struct device *dev, off_t addr, size_t size)
const struct spi_nor_config *params = dev->config->config_info;

/* should be between 0 and flash size */
if ((addr < 0) || ((size + addr) >
(params->sector_size * params->n_sectors))) {
if ((addr < 0) || ((size + addr) > params->size)) {
return -ENODEV;
}

@@ -269,33 +245,31 @@ static int spi_nor_erase(struct device *dev, off_t addr, size_t size)
/* write enable */
spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN);

if (size == (params->sector_size * params->n_sectors)) {
if (size == params->size) {
/* chip erase */
spi_nor_cmd_write(dev, SPI_NOR_CMD_CE);
size -= (params->sector_size * params->n_sectors);
} else if ((DT_JEDEC_SPI_NOR_0_ERASE_BLOCK_SIZE == SZ_64K)
&& (size >= SZ_64K)
&& ((addr & MASK_64K) == 0)) {
size -= params->size;
} else if ((size >= SPI_NOR_BLOCK_SIZE)
&& SPI_NOR_IS_BLOCK_ALIGNED(addr)) {
/* 64 KiB block erase */
spi_nor_cmd_addr_write(dev, SPI_NOR_CMD_BE, addr,
NULL, 0);
addr += SZ_64K;
size -= SZ_64K;
} else if ((DT_JEDEC_SPI_NOR_0_ERASE_BLOCK_SIZE == SZ_32K)
&& (size >= SZ_32K)
&& ((addr & MASK_32K) == 0)) {
addr += SPI_NOR_BLOCK_SIZE;
size -= SPI_NOR_BLOCK_SIZE;
} else if ((size >= SPI_NOR_BLOCK32_SIZE)
&& SPI_NOR_IS_BLOCK32_ALIGNED(addr)) {
/* 32 KiB block erase */
spi_nor_cmd_addr_write(dev, SPI_NOR_CMD_BE_32K, addr,
NULL, 0);
addr += SZ_32K;
size -= SZ_32K;
} else if ((size >= params->sector_size) &&
((addr & (params->sector_size - 1)) == 0)) {
addr += SPI_NOR_BLOCK32_SIZE;
size -= SPI_NOR_BLOCK32_SIZE;
} else if ((size >= SPI_NOR_SECTOR_SIZE)
&& SPI_NOR_IS_SECTOR_ALIGNED(addr)) {
/* sector erase */
spi_nor_cmd_addr_write(dev, SPI_NOR_CMD_SE, addr,
NULL, 0);
addr += params->sector_size;
size -= params->sector_size;
addr += SPI_NOR_SECTOR_SIZE;
size -= SPI_NOR_SECTOR_SIZE;
} else {
/* minimal erase size is at least a sector size */
SYNC_UNLOCK();
@@ -385,8 +359,8 @@ static int spi_nor_init(struct device *dev)

#if defined(CONFIG_FLASH_PAGE_LAYOUT)
static const struct flash_pages_layout dev_layout = {
.pages_count = DT_INST_0_JEDEC_SPI_NOR_SIZE / 8 / DT_JEDEC_SPI_NOR_0_ERASE_BLOCK_SIZE,
.pages_size = DT_JEDEC_SPI_NOR_0_ERASE_BLOCK_SIZE,
.pages_count = DT_INST_0_JEDEC_SPI_NOR_SIZE / 8 / SPI_NOR_BLOCK_SIZE,
.pages_size = SPI_NOR_BLOCK_SIZE,
};

static void spi_nor_pages_layout(struct device *dev,
@@ -415,9 +389,10 @@ static const struct spi_nor_config flash_id = {
DT_INST_0_JEDEC_SPI_NOR_JEDEC_ID_1,
DT_INST_0_JEDEC_SPI_NOR_JEDEC_ID_2,
},
.page_size = CONFIG_SPI_NOR_PAGE_SIZE,
.sector_size = CONFIG_SPI_NOR_SECTOR_SIZE,
.n_sectors = SECTORS_COUNT,
#ifdef DT_INST_0_JEDEC_SPI_NOR_HAS_BE32K
.has_be32k = true,
#endif /* DT_INST_0_JEDEC_SPI_NOR_HAS_BE32K */
.size = DT_INST_0_JEDEC_SPI_NOR_SIZE / 8,
};

static struct spi_nor_data spi_nor_memory_data;
@@ -12,10 +12,14 @@
#define SPI_NOR_MAX_ID_LEN 3

struct spi_nor_config {
/* JEDEC id from devicetree */
u8_t id[SPI_NOR_MAX_ID_LEN];
u32_t page_size;
u32_t sector_size;
u32_t n_sectors;

/* Indicates support for BE32K */
bool has_be32k;

/* Size from devicetree, in bytes */
u32_t size;
};

/* Status register bits */
@@ -35,4 +39,20 @@ struct spi_nor_config {
#define SPI_NOR_CMD_CE 0xC7 /* Chip erase */
#define SPI_NOR_CMD_RDID 0x9F /* Read JEDEC ID */

/* Page, sector, and block size are standard, not configurable. */
#define SPI_NOR_PAGE_SIZE 0x0100U
#define SPI_NOR_SECTOR_SIZE 0x1000U
#define SPI_NOR_BLOCK_SIZE 0x10000U

/* Some devices support erase operations on 32 KiBy blocks.
* Support is indicated by the has-be32k property.
*/
#define SPI_NOR_BLOCK32_SIZE 0x8000

/* Test whether offset is aligned. */
#define SPI_NOR_IS_PAGE_ALIGNED(_ofs) (((_ofs) & (SPI_NOR_PAGE_SIZE - 1U)) == 0)
#define SPI_NOR_IS_SECTOR_ALIGNED(_ofs) (((_ofs) & (SPI_NOR_SECTOR_SIZE - 1U)) == 0)
#define SPI_NOR_IS_BLOCK_ALIGNED(_ofs) (((_ofs) & (SPI_NOR_BLOCK_SIZE - 1U)) == 0)
#define SPI_NOR_IS_BLOCK32_ALIGNED(_ofs) (((_ofs) & (SPI_NOR_BLOCK32_SIZE - 1U)) == 0)

#endif /*__SPI_NOR_H__*/
@@ -21,10 +21,10 @@ properties:
category: required
description: JEDEC ID as manufacturer ID, memory type, memory density

erase-block-size:
type: int
description: address alignment required by flash erase operations
category: optional
has-be32k:
type: boolean
category: optional
description: Indicates the device supports the BE32K command

write-block-size:
type: int

0 comments on commit 2a590d3

Please sign in to comment.
You can’t perform that action at this time.