1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #13332 from bergzand/pr/mtd_spi_nor/params_struct

mtd_spi_nor: Move const params to separate struct
This commit is contained in:
Kaspar Schleiser 2020-02-26 09:43:18 +01:00 committed by GitHub
commit 2dcf65d942
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 89 additions and 59 deletions

View File

@ -48,6 +48,15 @@ static devfs_t mulle_nvram_devfs = {
.private_data = &mulle_nvram_dev,
};
static const mtd_spi_nor_params_t mulle_nor_params = {
.opcode = &mtd_spi_nor_opcode_default,
.spi = MULLE_NOR_SPI_DEV,
.cs = MULLE_NOR_SPI_CS,
.addr_width = 3,
.mode = SPI_MODE_3,
.clk = SPI_CLK_10MHZ,
};
static mtd_spi_nor_t mulle_nor_dev = {
.base = {
.driver = &mtd_spi_nor_driver,
@ -55,12 +64,7 @@ static mtd_spi_nor_t mulle_nor_dev = {
.pages_per_sector = 256,
.sector_count = 32,
},
.opcode = &mtd_spi_nor_opcode_default,
.spi = MULLE_NOR_SPI_DEV,
.cs = MULLE_NOR_SPI_CS,
.addr_width = 3,
.mode = SPI_MODE_3,
.clk = SPI_CLK_10MHZ,
.params = &mulle_nor_params,
};
mtd_dev_t *mtd0 = (mtd_dev_t *)&mulle_nor_dev;

View File

@ -83,6 +83,19 @@ typedef struct __attribute__((packed)) {
*/
#define SPI_NOR_F_SECT_32K (2)
/**
* @brief Compile-time parameters for a serial flash device
*/
typedef struct {
const mtd_spi_nor_opcode_t *opcode; /**< Opcode table for the device */
spi_clk_t clk; /**< SPI clock */
uint16_t flag; /**< Config flags */
spi_t spi; /**< SPI bus the device is connected to */
spi_mode_t mode; /**< SPI mode */
gpio_t cs; /**< CS pin GPIO handle */
uint8_t addr_width; /**< Number of bytes in addresses, usually 3 for small devices */
} mtd_spi_nor_params_t;
/**
* @brief Device descriptor for serial flash memory devices
*
@ -90,12 +103,7 @@ typedef struct __attribute__((packed)) {
*/
typedef struct {
mtd_dev_t base; /**< inherit from mtd_dev_t object */
const mtd_spi_nor_opcode_t *opcode; /**< Opcode table for the device */
spi_t spi; /**< SPI bus the device is connected to */
gpio_t cs; /**< CS pin GPIO handle */
spi_mode_t mode; /**< SPI mode */
spi_clk_t clk; /**< SPI clock */
uint16_t flag; /**< Config flags */
const mtd_spi_nor_params_t *params; /**< SPI NOR params */
mtd_jedec_id_t jedec_id; /**< JEDEC ID of the chip */
/**
* @brief bitmask to corresponding to the page address
@ -109,7 +117,6 @@ typedef struct {
* Computed by mtd_spi_nor_init, no need to touch outside the driver.
*/
uint32_t sec_addr_mask;
uint8_t addr_width; /**< Number of bytes in addresses, usually 3 for small devices */
/**
* @brief number of right shifts to get the address to the start of the page
*

View File

@ -79,6 +79,17 @@ const mtd_desc_t mtd_spi_nor_driver = {
.power = mtd_spi_nor_power,
};
static void mtd_spi_acquire(const mtd_spi_nor_t *dev)
{
spi_acquire(dev->params->spi, dev->params->cs,
dev->params->mode, dev->params->clk);
}
static void mtd_spi_release(const mtd_spi_nor_t *dev)
{
spi_release(dev->params->spi);
}
/**
* @internal
* @brief Send command opcode followed by address, followed by a read to buffer
@ -96,10 +107,10 @@ static void mtd_spi_cmd_addr_read(const mtd_spi_nor_t *dev, uint8_t opcode,
(void *)dev, (unsigned int)opcode, addr.u8[0], addr.u8[1], addr.u8[2],
addr.u8[3], dest, count);
uint8_t *addr_buf = &addr.u8[4 - dev->addr_width];
uint8_t *addr_buf = &addr.u8[4 - dev->params->addr_width];
if (ENABLE_TRACE) {
TRACE("mtd_spi_cmd_addr_read: addr:");
for (unsigned int i = 0; i < dev->addr_width; ++i) {
for (unsigned int i = 0; i < dev->params->addr_width; ++i) {
TRACE(" %02x", addr_buf[i]);
}
TRACE("\n");
@ -107,11 +118,13 @@ static void mtd_spi_cmd_addr_read(const mtd_spi_nor_t *dev, uint8_t opcode,
do {
/* Send opcode followed by address */
spi_transfer_byte(dev->spi, dev->cs, true, opcode);
spi_transfer_bytes(dev->spi, dev->cs, true, (char *)addr_buf, NULL, dev->addr_width);
spi_transfer_byte(dev->params->spi, dev->params->cs, true, opcode);
spi_transfer_bytes(dev->params->spi, dev->params->cs, true,
(char *)addr_buf, NULL, dev->params->addr_width);
/* Read data */
spi_transfer_bytes(dev->spi, dev->cs, false, NULL, dest, count);
spi_transfer_bytes(dev->params->spi, dev->params->cs, false,
NULL, dest, count);
} while (0);
}
@ -132,10 +145,10 @@ static void mtd_spi_cmd_addr_write(const mtd_spi_nor_t *dev, uint8_t opcode,
(void *)dev, (unsigned int)opcode, addr.u8[0], addr.u8[1], addr.u8[2],
addr.u8[3], src, count);
uint8_t *addr_buf = &addr.u8[4 - dev->addr_width];
uint8_t *addr_buf = &addr.u8[4 - dev->params->addr_width];
if (ENABLE_TRACE) {
TRACE("mtd_spi_cmd_addr_write: addr:");
for (unsigned int i = 0; i < dev->addr_width; ++i) {
for (unsigned int i = 0; i < dev->params->addr_width; ++i) {
TRACE(" %02x", addr_buf[i]);
}
TRACE("\n");
@ -143,12 +156,14 @@ static void mtd_spi_cmd_addr_write(const mtd_spi_nor_t *dev, uint8_t opcode,
do {
/* Send opcode followed by address */
spi_transfer_byte(dev->spi, dev->cs, true, opcode);
spi_transfer_byte(dev->params->spi, dev->params->cs, true, opcode);
bool cont = (count > 0); /* only keep CS asserted when there is data that follows */
spi_transfer_bytes(dev->spi, dev->cs, cont, (char *)addr_buf, NULL, dev->addr_width);
spi_transfer_bytes(dev->params->spi, dev->params->cs, cont,
(char *)addr_buf, NULL, dev->params->addr_width);
/* Write data */
if (cont) {
spi_transfer_bytes(dev->spi, dev->cs, false, (void *)src, NULL, count);
spi_transfer_bytes(dev->params->spi, dev->params->cs,
false, (void *)src, NULL, count);
}
} while (0);
}
@ -167,7 +182,7 @@ static void mtd_spi_cmd_read(const mtd_spi_nor_t *dev, uint8_t opcode, void *des
TRACE("mtd_spi_cmd_read: %p, %02x, %p, %" PRIu32 "\n",
(void *)dev, (unsigned int)opcode, dest, count);
spi_transfer_regs(dev->spi, dev->cs, opcode, NULL, dest, count);
spi_transfer_regs(dev->params->spi, dev->params->cs, opcode, NULL, dest, count);
}
/**
@ -184,7 +199,8 @@ static void __attribute__((unused)) mtd_spi_cmd_write(const mtd_spi_nor_t *dev,
TRACE("mtd_spi_cmd_write: %p, %02x, %p, %" PRIu32 "\n",
(void *)dev, (unsigned int)opcode, src, count);
spi_transfer_regs(dev->spi, dev->cs, opcode, (void *)src, NULL, count);
spi_transfer_regs(dev->params->spi, dev->params->cs, opcode,
(void *)src, NULL, count);
}
/**
@ -199,7 +215,7 @@ static void mtd_spi_cmd(const mtd_spi_nor_t *dev, uint8_t opcode)
TRACE("mtd_spi_cmd: %p, %02x\n",
(void *)dev, (unsigned int)opcode);
spi_transfer_byte(dev->spi, dev->cs, false, opcode);
spi_transfer_byte(dev->params->spi, dev->params->cs, false, opcode);
}
/**
@ -225,15 +241,17 @@ static int mtd_spi_read_jedec_id(const mtd_spi_nor_t *dev, mtd_jedec_id_t *out)
int status = 0;
mtd_jedec_id_t jedec;
DEBUG("mtd_spi_read_jedec_id: rdid=0x%02x\n", (unsigned int)dev->opcode->rdid);
DEBUG("mtd_spi_read_jedec_id: rdid=0x%02x\n",
(unsigned int)dev->params->opcode->rdid);
/* Send opcode */
spi_transfer_byte(dev->spi, dev->cs, true, dev->opcode->rdid);
spi_transfer_byte(dev->params->spi, dev->params->cs, true, dev->params->opcode->rdid);
/* Read manufacturer ID */
jedec.bank = 1;
while (status == 0) {
jedec.manuf = spi_transfer_byte(dev->spi, dev->cs, true, 0);
jedec.manuf = spi_transfer_byte(dev->params->spi,
dev->params->cs, true, 0);
if (jedec.manuf == JEDEC_NEXT_BANK) {
/* next bank, see JEP106 */
DEBUG("mtd_spi_read_jedec_id: manuf bank incr\n");
@ -256,7 +274,8 @@ static int mtd_spi_read_jedec_id(const mtd_spi_nor_t *dev, mtd_jedec_id_t *out)
/* Read device ID */
if (status == 0) {
spi_transfer_bytes(dev->spi, dev->cs, false, NULL, (char *)&jedec.device[0], sizeof(jedec.device));
spi_transfer_bytes(dev->params->spi, dev->params->cs, false, NULL,
(char *)&jedec.device[0], sizeof(jedec.device));
}
DEBUG("mtd_spi_read_jedec_id: device=0x%02x, 0x%02x\n",
(unsigned int)jedec.device[0], (unsigned int)jedec.device[1]);
@ -277,7 +296,7 @@ static inline void wait_for_write_complete(const mtd_spi_nor_t *dev, uint32_t us
#endif
do {
uint8_t status;
mtd_spi_cmd_read(dev, dev->opcode->rdsr, &status, sizeof(status));
mtd_spi_cmd_read(dev, dev->params->opcode->rdsr, &status, sizeof(status));
TRACE("mtd_spi_nor: wait device status = 0x%02x\n", (unsigned int)status);
if ((status & 1) == 0) { /* TODO magic number */
@ -321,7 +340,7 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)
mtd_spi_nor_t *dev = (mtd_spi_nor_t *)mtd;
DEBUG("mtd_spi_nor_init: -> spi: %lx, cs: %lx, opcodes: %p\n",
(unsigned long)dev->spi, (unsigned long)dev->cs, (void *)dev->opcode);
(unsigned long)dev->params->spi, (unsigned long)dev->params->cs, (void *)dev->params->opcode);
DEBUG("mtd_spi_nor_init: %" PRIu32 " bytes "
"(%" PRIu32 " sectors, %" PRIu32 " bytes/sector, "
@ -331,28 +350,28 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)
mtd->sector_count, mtd->pages_per_sector * mtd->page_size,
mtd->pages_per_sector * mtd->sector_count,
mtd->pages_per_sector, mtd->page_size);
DEBUG("mtd_spi_nor_init: Using %u byte addresses\n", dev->addr_width);
DEBUG("mtd_spi_nor_init: Using %u byte addresses\n", dev->params->addr_width);
if (dev->addr_width == 0) {
if (dev->params->addr_width == 0) {
return -EINVAL;
}
/* CS */
DEBUG("mtd_spi_nor_init: CS init\n");
spi_init_cs(dev->spi, dev->cs);
spi_init_cs(dev->params->spi, dev->params->cs);
spi_acquire(dev->spi, dev->cs, dev->mode, dev->clk);
mtd_spi_acquire(dev);
int res = mtd_spi_read_jedec_id(dev, &dev->jedec_id);
if (res < 0) {
spi_release(dev->spi);
mtd_spi_release(dev);
return -EIO;
}
DEBUG("mtd_spi_nor_init: Found chip with ID: (%d, 0x%02x, 0x%02x, 0x%02x)\n",
dev->jedec_id.bank, dev->jedec_id.manuf, dev->jedec_id.device[0], dev->jedec_id.device[1]);
uint8_t status;
mtd_spi_cmd_read(dev, dev->opcode->rdsr, &status, sizeof(status));
spi_release(dev->spi);
mtd_spi_cmd_read(dev, dev->params->opcode->rdsr, &status, sizeof(status));
mtd_spi_release(dev);
DEBUG("mtd_spi_nor_init: device status = 0x%02x\n", (unsigned int)status);
@ -416,9 +435,9 @@ static int mtd_spi_nor_read(mtd_dev_t *mtd, void *dest, uint32_t addr, uint32_t
}
be_uint32_t addr_be = byteorder_htonl(addr);
spi_acquire(dev->spi, dev->cs, dev->mode, dev->clk);
mtd_spi_cmd_addr_read(dev, dev->opcode->read, addr_be, dest, size);
spi_release(dev->spi);
mtd_spi_acquire(dev);
mtd_spi_cmd_addr_read(dev, dev->params->opcode->read, addr_be, dest, size);
mtd_spi_release(dev);
return size;
}
@ -447,17 +466,17 @@ static int mtd_spi_nor_write(mtd_dev_t *mtd, const void *src, uint32_t addr, uin
}
be_uint32_t addr_be = byteorder_htonl(addr);
spi_acquire(dev->spi, dev->cs, dev->mode, dev->clk);
mtd_spi_acquire(dev);
/* write enable */
mtd_spi_cmd(dev, dev->opcode->wren);
mtd_spi_cmd(dev, dev->params->opcode->wren);
/* Page program */
mtd_spi_cmd_addr_write(dev, dev->opcode->page_program, addr_be, src, size);
mtd_spi_cmd_addr_write(dev, dev->params->opcode->page_program, addr_be, src, size);
/* waiting for the command to complete before returning */
wait_for_write_complete(dev, 0);
spi_release(dev->spi);
mtd_spi_release(dev);
return size;
}
@ -485,36 +504,36 @@ static int mtd_spi_nor_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size)
return -EOVERFLOW;
}
spi_acquire(dev->spi, dev->cs, dev->mode, dev->clk);
mtd_spi_acquire(dev);
while (size) {
uint32_t us;
be_uint32_t addr_be = byteorder_htonl(addr);
/* write enable */
mtd_spi_cmd(dev, dev->opcode->wren);
mtd_spi_cmd(dev, dev->params->opcode->wren);
if (size == total_size) {
mtd_spi_cmd(dev, dev->opcode->chip_erase);
mtd_spi_cmd(dev, dev->params->opcode->chip_erase);
size -= total_size;
us = MTD_SPI_NOR_WAIT_C_ER;
}
else if ((dev->flag & SPI_NOR_F_SECT_32K) && (size >= MTD_32K) &&
else if ((dev->params->flag & SPI_NOR_F_SECT_32K) && (size >= MTD_32K) &&
((addr & MTD_32K_ADDR_MASK) == 0)) {
/* 32 KiB blocks can be erased with block erase command */
mtd_spi_cmd_addr_write(dev, dev->opcode->block_erase_32k, addr_be, NULL, 0);
mtd_spi_cmd_addr_write(dev, dev->params->opcode->block_erase_32k, addr_be, NULL, 0);
addr += MTD_32K;
size -= MTD_32K;
us = MTD_SPI_NOR_WAIT_32K_ER;
}
else if ((dev->flag & SPI_NOR_F_SECT_4K) && (size >= MTD_4K) &&
else if ((dev->params->flag & SPI_NOR_F_SECT_4K) && (size >= MTD_4K) &&
((addr & MTD_4K_ADDR_MASK) == 0)) {
/* 4 KiB sectors can be erased with sector erase command */
mtd_spi_cmd_addr_write(dev, dev->opcode->sector_erase, addr_be, NULL, 0);
mtd_spi_cmd_addr_write(dev, dev->params->opcode->sector_erase, addr_be, NULL, 0);
addr += MTD_4K;
size -= MTD_4K;
us = MTD_SPI_NOR_WAIT_4K_ER;
}
else {
mtd_spi_cmd_addr_write(dev, dev->opcode->block_erase, addr_be, NULL, 0);
mtd_spi_cmd_addr_write(dev, dev->params->opcode->block_erase, addr_be, NULL, 0);
addr += sector_size;
size -= sector_size;
us = MTD_SPI_NOR_WAIT_S_ER;
@ -523,7 +542,7 @@ static int mtd_spi_nor_erase(mtd_dev_t *mtd, uint32_t addr, uint32_t size)
/* waiting for the command to complete before continuing */
wait_for_write_complete(dev, us);
}
spi_release(dev->spi);
mtd_spi_release(dev);
return 0;
}
@ -532,16 +551,16 @@ static int mtd_spi_nor_power(mtd_dev_t *mtd, enum mtd_power_state power)
{
mtd_spi_nor_t *dev = (mtd_spi_nor_t *)mtd;
spi_acquire(dev->spi, dev->cs, dev->mode, dev->clk);
mtd_spi_acquire(dev);
switch (power) {
case MTD_POWER_UP:
mtd_spi_cmd(dev, dev->opcode->wake);
mtd_spi_cmd(dev, dev->params->opcode->wake);
break;
case MTD_POWER_DOWN:
mtd_spi_cmd(dev, dev->opcode->sleep);
mtd_spi_cmd(dev, dev->params->opcode->sleep);
break;
}
spi_release(dev->spi);
mtd_spi_release(dev);
return 0;
}