Skip to content

Commit

Permalink
feat(spi_nand_flash): add support for Micron MT29F2G01ABAGD
Browse files Browse the repository at this point in the history
  • Loading branch information
igrr committed Oct 9, 2024
1 parent ddfc93b commit 1fd2027
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 12 deletions.
85 changes: 78 additions & 7 deletions spi_nand_flash/src/dhara_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,15 @@ int dhara_nand_is_bad(const struct dhara_nand *n, dhara_block_t b)

ESP_GOTO_ON_ERROR(read_page_and_wait(dev, first_block_page, NULL), fail, TAG, "");

uint16_t column_addr = dev->page_size;

if (dev->flags & NAND_FLAG_HAS_READ_PLANE_SELECT) {
uint32_t plane = b % dev->num_planes;
column_addr += plane << dev->dhara_nand.log2_page_size;
}

// Read the first 2 bytes on the OOB of the first page in the block. This should be 0xFFFF for a good block
ESP_GOTO_ON_ERROR(spi_nand_read(dev->config.device_handle, (uint8_t *) &bad_block_indicator, dev->page_size, 2),
ESP_GOTO_ON_ERROR(spi_nand_read(dev->config.device_handle, (uint8_t *) &bad_block_indicator, column_addr, 2),
fail, TAG, "");

ESP_LOGD(TAG, "is_bad, block=%"PRIu32", page=%"PRIu32",indicator = %04x", b, first_block_page, bad_block_indicator);
Expand All @@ -94,8 +101,14 @@ void dhara_nand_mark_bad(const struct dhara_nand *n, dhara_block_t b)
fail, TAG, "");

ESP_GOTO_ON_ERROR(spi_nand_write_enable(dev->config.device_handle), fail, TAG, "");

uint32_t column_addr = dev->page_size;
if (dev->flags & NAND_FLAG_HAS_READ_PLANE_SELECT) {
uint32_t plane = b % dev->num_planes;
column_addr += plane << dev->dhara_nand.log2_page_size;
}
ESP_GOTO_ON_ERROR(spi_nand_program_load(dev->config.device_handle, (const uint8_t *) &bad_block_indicator,
dev->page_size, 2),
column_addr, 2),
fail, TAG, "");
ESP_GOTO_ON_ERROR(program_execute_and_wait(dev, first_block_page, NULL), fail, TAG, "");
return;
Expand Down Expand Up @@ -138,13 +151,20 @@ int dhara_nand_prog(const struct dhara_nand *n, dhara_page_t p, const uint8_t *d
esp_err_t ret;
uint8_t status;
uint16_t used_marker = 0;
uint32_t column_addr = 0;

if (dev->flags & NAND_FLAG_HAS_PROG_PLANE_SELECT) {
uint32_t block = p >> dev->dhara_nand.log2_ppb;
uint32_t plane = block % dev->num_planes;
column_addr += plane << dev->dhara_nand.log2_page_size;
}

ESP_GOTO_ON_ERROR(read_page_and_wait(dev, p, NULL), fail, TAG, "");
ESP_GOTO_ON_ERROR(spi_nand_write_enable(dev->config.device_handle), fail, TAG, "");
ESP_GOTO_ON_ERROR(spi_nand_program_load(dev->config.device_handle, data, 0, dev->page_size),
ESP_GOTO_ON_ERROR(spi_nand_program_load(dev->config.device_handle, data, column_addr, dev->page_size),
fail, TAG, "");
ESP_GOTO_ON_ERROR(spi_nand_program_load(dev->config.device_handle, (uint8_t *)&used_marker,
dev->page_size + 2, 2),
column_addr + dev->page_size + 2, 2),
fail, TAG, "");
ESP_GOTO_ON_ERROR(program_execute_and_wait(dev, p, &status), fail, TAG, "");

Expand All @@ -167,8 +187,16 @@ int dhara_nand_is_free(const struct dhara_nand *n, dhara_page_t p)
uint16_t used_marker;

ESP_GOTO_ON_ERROR(read_page_and_wait(dev, p, NULL), fail, TAG, "");

uint16_t column_addr = dev->page_size + 2;
if (dev->flags & NAND_FLAG_HAS_READ_PLANE_SELECT) {
uint32_t block = p >> dev->dhara_nand.log2_ppb;
uint32_t plane = block % dev->num_planes;
column_addr += plane << dev->dhara_nand.log2_page_size;
}

ESP_GOTO_ON_ERROR(spi_nand_read(dev->config.device_handle, (uint8_t *)&used_marker,
dev->page_size + 2, 2),
column_addr, 2),
fail, TAG, "");

ESP_LOGD(TAG, "is free, page=%"PRIu32", used_marker=%04x,", p, used_marker);
Expand Down Expand Up @@ -200,7 +228,14 @@ int dhara_nand_read(const struct dhara_nand *n, dhara_page_t p, size_t offset, s
return -1;
}

ESP_GOTO_ON_ERROR(spi_nand_read(dev->config.device_handle, data, offset, length), fail, TAG, "");
uint16_t column_addr = offset;
if (dev->flags & NAND_FLAG_HAS_READ_PLANE_SELECT) {
uint32_t block = p >> dev->dhara_nand.log2_ppb;
uint32_t plane = block % dev->num_planes;
column_addr += plane << dev->dhara_nand.log2_page_size;
}

ESP_GOTO_ON_ERROR(spi_nand_read(dev->config.device_handle, data, column_addr, length), fail, TAG, "");

return 0;
fail:
Expand All @@ -222,8 +257,44 @@ int dhara_nand_copy(const struct dhara_nand *n, dhara_page_t src, dhara_page_t d
dhara_set_error(err, DHARA_E_ECC);
return -1;
}

ESP_GOTO_ON_ERROR(spi_nand_write_enable(dev->config.device_handle), fail, TAG, "");

bool need_copy_via_ram = false;
if (dev->num_planes > 1 && (dev->flags & (NAND_FLAG_HAS_PROG_PLANE_SELECT | NAND_FLAG_HAS_READ_PLANE_SELECT))) {
uint32_t src_block = src >> dev->dhara_nand.log2_ppb;
uint32_t dst_block = dst >> dev->dhara_nand.log2_ppb;
need_copy_via_ram = src_block % dev->num_planes != dst_block % dev->num_planes;
}

if (need_copy_via_ram) {
uint8_t *copy_buf = malloc(dev->page_size + 2);
ESP_GOTO_ON_FALSE(copy_buf, ESP_ERR_NO_MEM, fail, TAG, "Failed to allocate copy buffer");

uint32_t src_column_addr = 0;
if (dev->flags & NAND_FLAG_HAS_READ_PLANE_SELECT) {
uint32_t src_block = src >> dev->dhara_nand.log2_ppb;
uint32_t plane = src_block % dev->num_planes;
src_column_addr += plane << dev->dhara_nand.log2_page_size;
}

uint32_t dst_column_addr = 0;
if (dev->flags & NAND_FLAG_HAS_PROG_PLANE_SELECT) {
uint32_t dst_block = dst >> dev->dhara_nand.log2_ppb;
uint32_t plane = dst_block % dev->num_planes;
dst_column_addr += plane << dev->dhara_nand.log2_page_size;
}

ESP_GOTO_ON_ERROR(spi_nand_read(dev->config.device_handle, copy_buf, src_column_addr, dev->page_size), fail, TAG, "");

ESP_GOTO_ON_ERROR(spi_nand_program_load(dev->config.device_handle, copy_buf, dst_column_addr, dev->page_size),
fail, TAG, "");
uint16_t used_marker = 0;
ESP_GOTO_ON_ERROR(spi_nand_program_load(dev->config.device_handle, (uint8_t *)&used_marker,
dst_column_addr + dev->page_size + 2, 2),
fail, TAG, "");
free(copy_buf);
}

ESP_GOTO_ON_ERROR(program_execute_and_wait(dev, dst, &status), fail, TAG, "");

if ((status & STAT_PROGRAM_FAILED) != 0) {
Expand Down
21 changes: 16 additions & 5 deletions spi_nand_flash/src/nand.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,15 +139,24 @@ static esp_err_t spi_nand_micron_init(spi_nand_flash_device_t *dev)
.miso_data = &device_id
};
spi_nand_execute_transaction(dev->config.device_handle, &t);
dev->read_page_delay_us = 115;
dev->erase_block_delay_us = 2000;
dev->program_page_delay_us = 240;
switch (device_id) {
case MICRON_DI_34:
dev->read_page_delay_us = 115;
dev->program_page_delay_us = 240;
dev->dhara_nand.num_blocks = 2048;
dev->dhara_nand.log2_ppb = 6; // 64 pages per block
dev->dhara_nand.log2_page_size = 12; // 4096 bytes per page
break;
case MICRON_DI_24:
dev->read_page_delay_us = 55;
dev->program_page_delay_us = 220;
dev->dhara_nand.num_blocks = 2048;
dev->dhara_nand.log2_ppb = 6; // 64 pages per block
dev->dhara_nand.log2_page_size = 11; // 2048 bytes per page
dev->flags |= NAND_FLAG_HAS_PROG_PLANE_SELECT | NAND_FLAG_HAS_READ_PLANE_SELECT;
dev->num_planes = 2;
break;
default:
return ESP_ERR_INVALID_RESPONSE;
}
Expand Down Expand Up @@ -222,6 +231,8 @@ esp_err_t spi_nand_flash_init_device(spi_nand_flash_config_t *config, spi_nand_f
(*handle)->block_size = (1 << (*handle)->dhara_nand.log2_ppb) * (*handle)->page_size;
(*handle)->num_blocks = (*handle)->dhara_nand.num_blocks;
(*handle)->work_buffer = malloc((*handle)->page_size);
(*handle)->num_planes = 1;
(*handle)->flags = 0;

ESP_GOTO_ON_FALSE((*handle)->work_buffer != NULL, ESP_ERR_NO_MEM, fail, TAG, "nomem");

Expand Down Expand Up @@ -276,7 +287,7 @@ esp_err_t spi_nand_erase_chip(spi_nand_flash_device_t *handle)

esp_err_t spi_nand_flash_read_sector(spi_nand_flash_device_t *handle, uint8_t *buffer, dhara_sector_t sector_id)
{
dhara_error_t err;
dhara_error_t err = 0;
esp_err_t ret = ESP_OK;

xSemaphoreTake(handle->mutex, portMAX_DELAY);
Expand All @@ -296,7 +307,7 @@ esp_err_t spi_nand_flash_read_sector(spi_nand_flash_device_t *handle, uint8_t *b

esp_err_t spi_nand_flash_write_sector(spi_nand_flash_device_t *handle, const uint8_t *buffer, dhara_sector_t sector_id)
{
dhara_error_t err;
dhara_error_t err = 0;
esp_err_t ret = ESP_OK;

xSemaphoreTake(handle->mutex, portMAX_DELAY);
Expand All @@ -311,7 +322,7 @@ esp_err_t spi_nand_flash_write_sector(spi_nand_flash_device_t *handle, const uin

esp_err_t spi_nand_flash_sync(spi_nand_flash_device_t *handle)
{
dhara_error_t err;
dhara_error_t err = 0;
esp_err_t ret = ESP_OK;

xSemaphoreTake(handle->mutex, portMAX_DELAY);
Expand Down
6 changes: 6 additions & 0 deletions spi_nand_flash/src/nand.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,17 @@ extern "C" {

#define INVALID_PAGE 0xFFFF

#define NAND_FLAG_HAS_QE BIT(0)
#define NAND_FLAG_HAS_PROG_PLANE_SELECT BIT(1)
#define NAND_FLAG_HAS_READ_PLANE_SELECT BIT(2)

struct spi_nand_flash_device_t {
spi_nand_flash_config_t config;
uint32_t block_size;
uint32_t page_size;
uint32_t num_blocks;
uint32_t num_planes;
uint32_t flags;
struct dhara_map dhara_map;
struct dhara_nand dhara_nand;
uint8_t *work_buffer;
Expand Down
1 change: 1 addition & 0 deletions spi_nand_flash/src/nand_flash_devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@
#define WINBOND_DI_BC21 0xBC21

#define MICRON_DI_34 0x34
#define MICRON_DI_24 0x24 // MT29F2G

0 comments on commit 1fd2027

Please sign in to comment.