x1000: NAND driver bugfixes

- Missing mutex unlock in nand_open()
- SET_FEATURE command incorrectly issued as a read operation
- Inverted protection bits, not sure how that happened...
- Block erase skipped ahead by a wrong amount, causing erases
  spanning multiple blocks to erase the wrong blocks

This code was buggy as hell... it's in need of a major overhaul.
It's not very flexible or reliable, and access to the flash is
useful during development of a new port, even if not useful once
the port is complete.

Change-Id: Ib85ee7453beab9657e3d19798ebaa09174b3649e
This commit is contained in:
Aidan MacDonald 2021-06-12 00:22:48 +01:00
parent 02c4ec294c
commit 2d6ddd0c5b
3 changed files with 12 additions and 11 deletions

View file

@ -46,9 +46,9 @@
#define NAND_FREG_PROTECTION_BRWD 0x80 #define NAND_FREG_PROTECTION_BRWD 0x80
#define NAND_FREG_PROTECTION_BP2 0x20 #define NAND_FREG_PROTECTION_BP2 0x20
#define NAND_FREG_PROTECTION_BP1 0x10 #define NAND_FREG_PROTECTION_BP1 0x10
#define NAND_FREG_PROTECTION_BP0 0x80 #define NAND_FREG_PROTECTION_BP0 0x08
/* Mask of BP bits 0-2 */ /* Mask of BP bits 0-2 */
#define NAND_FREG_PROTECTION_ALLBP (0x38) #define NAND_FREG_PROTECTION_ALLBP 0x38
/* Feature register bits */ /* Feature register bits */
#define NAND_FREG_FEATURE_QE 0x01 #define NAND_FREG_FEATURE_QE 0x01
@ -129,6 +129,7 @@ int nand_open(void)
sfc_set_dev_conf(chip_data->dev_conf); sfc_set_dev_conf(chip_data->dev_conf);
sfc_set_clock(chip_data->clock_freq); sfc_set_clock(chip_data->clock_freq);
sfc_unlock();
return NAND_SUCCESS; return NAND_SUCCESS;
} }
@ -237,7 +238,7 @@ int nand_erase(uint32_t addr, uint32_t size)
{ {
const uint32_t page_size = 1 << nand_drv.chip_data->log2_page_size; const uint32_t page_size = 1 << nand_drv.chip_data->log2_page_size;
const uint32_t block_size = page_size << nand_drv.chip_data->log2_block_size; const uint32_t block_size = page_size << nand_drv.chip_data->log2_block_size;
const uint32_t pages_per_block = 1 << nand_drv.chip_data->log2_page_size; const uint32_t pages_per_block = 1 << nand_drv.chip_data->log2_block_size;
if(addr & (block_size - 1)) if(addr & (block_size - 1))
return NAND_ERR_UNALIGNED; return NAND_ERR_UNALIGNED;
@ -333,13 +334,13 @@ static int nandop_set_write_protect(bool en)
return val; return val;
if(en) { if(en) {
val &= ~NAND_FREG_PROTECTION_ALLBP;
if(nand_drv.chip_data->flags & NANDCHIP_FLAG_USE_BRWD)
val &= ~NAND_FREG_PROTECTION_BRWD;
} else {
val |= NAND_FREG_PROTECTION_ALLBP; val |= NAND_FREG_PROTECTION_ALLBP;
if(nand_drv.chip_data->flags & NANDCHIP_FLAG_USE_BRWD) if(nand_drv.chip_data->flags & NANDCHIP_FLAG_USE_BRWD)
val |= NAND_FREG_PROTECTION_BRWD; val |= NAND_FREG_PROTECTION_BRWD;
} else {
val &= ~NAND_FREG_PROTECTION_ALLBP;
if(nand_drv.chip_data->flags & NANDCHIP_FLAG_USE_BRWD)
val &= ~NAND_FREG_PROTECTION_BRWD;
} }
/* NOTE: The WP pin typically only protects changes to the protection /* NOTE: The WP pin typically only protects changes to the protection
@ -406,7 +407,7 @@ static int nandcmd_set_feature(uint8_t reg, uint8_t val)
{ {
sfc_op op = {0}; sfc_op op = {0};
op.command = NAND_CMD_SET_FEATURE; op.command = NAND_CMD_SET_FEATURE;
op.flags = SFC_FLAG_READ; op.flags = SFC_FLAG_WRITE;
op.addr_bytes = 1; op.addr_bytes = 1;
op.addr_lo = reg; op.addr_lo = reg;
op.data_bytes = 1; op.data_bytes = 1;

View file

@ -99,7 +99,7 @@ extern int nand_enable_writes(bool en);
extern int nand_read(uint32_t addr, uint32_t size, uint8_t* buf); extern int nand_read(uint32_t addr, uint32_t size, uint8_t* buf);
extern int nand_write(uint32_t addr, uint32_t size, const uint8_t* buf); extern int nand_write(uint32_t addr, uint32_t size, const uint8_t* buf);
/* Ereas eoperates on whole blocks. Like the page read/write operations, /* Erase operates on whole blocks. Like the page read/write operations,
* the address and size must be aligned to a multiple of the block size. * the address and size must be aligned to a multiple of the block size.
* If not, no blocks are erased and an error code is returned. */ * If not, no blocks are erased and an error code is returned. */
extern int nand_erase(uint32_t addr, uint32_t size); extern int nand_erase(uint32_t addr, uint32_t size);

View file

@ -166,7 +166,7 @@ void SFC(void)
* so please do NOT try to rearrange the code without testing it first! * so please do NOT try to rearrange the code without testing it first!
*/ */
void sfc_fifo_read(unsigned* buffer, int data_bytes) static void sfc_fifo_read(unsigned* buffer, int data_bytes)
{ {
int data_words = (data_bytes + 3) / 4; int data_words = (data_bytes + 3) / 4;
while(data_words > 0) { while(data_words > 0) {
@ -183,7 +183,7 @@ void sfc_fifo_read(unsigned* buffer, int data_bytes)
} }
} }
void sfc_fifo_write(const unsigned* buffer, int data_bytes) static void sfc_fifo_write(const unsigned* buffer, int data_bytes)
{ {
int data_words = (data_bytes + 3) / 4; int data_words = (data_bytes + 3) / 4;
while(data_words > 0) { while(data_words > 0) {