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

drivers/mtd_spi_nor: derive capacity from JEDEC ID

Most manufacturers (Spansion, Micron & ISSI) just encode the capacity
in the second ID byte.

Old Adesto (Atmel) chips use a different scheme here.
This commit is contained in:
Benjamin Valentin 2020-05-14 22:06:22 +02:00 committed by Benjamin Valentin
parent 3d3d6062f0
commit 585928f23d

View File

@ -54,6 +54,21 @@
#define MTD_4K (4096ul)
#define MTD_4K_ADDR_MASK (0xFFF)
#define MBIT_AS_BYTES ((1024 * 1024) / 8)
/**
* @brief JEDEC memory manufacturer ID codes.
*
* see http://www.softnology.biz/pdf/JEP106AV.pdf
* @{
*/
#define JEDEC_BANK(n) ((n) << 8)
typedef enum {
SPI_NOR_JEDEC_ATMEL = 0x1F | JEDEC_BANK(1),
} jedec_manuf_t;
/** @} */
static int mtd_spi_nor_init(mtd_dev_t *mtd);
static int mtd_spi_nor_read(mtd_dev_t *mtd, void *dest, uint32_t addr, uint32_t size);
static int mtd_spi_nor_write(mtd_dev_t *mtd, const void *src, uint32_t addr, uint32_t size);
@ -79,6 +94,11 @@ static void mtd_spi_release(const mtd_spi_nor_t *dev)
spi_release(dev->params->spi);
}
static bool mtd_spi_manuf_match(const mtd_jedec_id_t *id, jedec_manuf_t manuf)
{
return manuf == ((id->bank << 8) | id->manuf);
}
/**
* @internal
* @brief Send command opcode followed by address, followed by a read to buffer
@ -281,6 +301,28 @@ static int mtd_spi_read_jedec_id(const mtd_spi_nor_t *dev, mtd_jedec_id_t *out)
return status;
}
/**
* @internal
* @brief Get Flash capacity based on JEDEC ID
*
* @note The way the capacity is encoded differs between vendors.
* This formula has been tested with flash chips from Adesto,
* ISSI, Micron and Spansion, but it might not cover all cases.
* Please extend the function if necessary.
*/
static uint32_t mtd_spi_nor_get_size(const mtd_jedec_id_t *id)
{
/* old Atmel (now Adesto) parts use 5 lower bits of device ID 1 for density */
if (mtd_spi_manuf_match(id, SPI_NOR_JEDEC_ATMEL) &&
/* ID 2 is used to encode the product version, usually 1 or 2 */
(id->device[1] & ~0x3) == 0) {
return (0x1F & id->device[0]) * MBIT_AS_BYTES;
}
/* everyone else seems to use device ID 2 for density */
return 1 << id->device[1];
}
static inline void wait_for_write_complete(const mtd_spi_nor_t *dev, uint32_t us)
{
unsigned i = 0, j = 0;
@ -370,6 +412,12 @@ static int mtd_spi_nor_init(mtd_dev_t *mtd)
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]);
/* derive density from JEDEC ID */
if (mtd->sector_count == 0) {
mtd->sector_count = mtd_spi_nor_get_size(&dev->jedec_id)
/ (mtd->pages_per_sector * mtd->page_size);
}
uint8_t status;
mtd_spi_cmd_read(dev, dev->params->opcode->rdsr, &status, sizeof(status));
mtd_spi_release(dev);