Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(spi_nand_flash): add support for Micron MT29F2G chips #397

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading