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:
commit
2dcf65d942
@ -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;
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user