Onda VX747: get NAND driver working

generic NAND ID driver: clean up


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19817 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Maurus Cuelenaere 2009-01-22 00:04:20 +00:00
parent e79fc8aaef
commit 311d2f12ed
3 changed files with 66 additions and 54 deletions

View file

@ -24,35 +24,38 @@
struct nand_manufacturer
{
unsigned char id;
struct nand_info* info;
unsigned char id;
struct nand_info* info;
unsigned short total;
};
/* { pages_per_block, blocks_per_bank, page_size, spare_size, col_cycles, row_cycles } */
static const struct nand_info samsung[] =
{
/* K9F4G08UOM */
{0xDC, 0x10, 64, 4096, 2048, 64, 2, 3},
/* K9K8G08UOM */
{0xD3, 0x51, 64, 8192, 2048, 64, 2, 3},
/* K9LAG08UOM */
{0xD5, 0x55, 128, 8192, 2048, 64, 2, 3},
/* K9LBG08UOM, K9HBG08U1M, K9MCG08U5M */
{0xD7, 0x55, 128, 8192, 4096, 128, 2, 3}
/* { id1, id2, pages_per_block, blocks_per_bank, page_size, spare_size, col_cycles, row_cycles } */
/* K9F4G08UOM */
{0xDC, 0x10, 64, 4096, 2048, 64, 2, 3 },
/* K9K8G08UOM */
{0xD3, 0x51, 64, 8192, 2048, 64, 2, 3 },
/* K9LAG08UOM */
{0xD5, 0x55, 128, 8192, 2048, 64, 2, 3 },
/* K9LBG08UOM, K9HBG08U1M, K9MCG08U5M */
{0xD7, 0x55, 128, 8192, 4096, 128, 2, 3 },
};
#define M(id, x) {id, (struct nand_info*)x, (sizeof(x)/sizeof(struct nand_info))}
#define NI(id, x) {id, (struct nand_info*)x, (sizeof(x)/sizeof(struct nand_info))}
static const struct nand_manufacturer all[] =
{
M(0xEC, samsung),
NI(0xEC, samsung),
};
// --------------------------------------------------------------------------------------------------
struct nand_info* nand_identify(unsigned char data[5])
{
unsigned int i;
int found = -1;
for(i = 0; i < (sizeof(all)/sizeof(struct nand_manufacturer)); i++)
{
if(data[0] == all[i].id)
@ -61,6 +64,7 @@ struct nand_info* nand_identify(unsigned char data[5])
break;
}
}
if(found < 0)
return NULL;

View file

@ -1762,14 +1762,16 @@
#define EMC_SACR_MASK_MASK (0xff << EMC_SACR_MASK_BIT)
/* NAND Flash Control/Status Register */
#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */
#define EMC_NFCSR_NFCE4 (1 << 7) /* NAND Flash Enable */
#define EMC_NFCSR_NFE4 (1 << 6) /* NAND Flash FCE# Assertion Enable */
#define EMC_NFCSR_NFCE3 (1 << 5)
#define EMC_NFCSR_NFCE3 (1 << 5)
#define EMC_NFCSR_NFE3 (1 << 4)
#define EMC_NFCSR_NFCE2 (1 << 3)
#define EMC_NFCSR_NFCE2 (1 << 3)
#define EMC_NFCSR_NFE2 (1 << 2)
#define EMC_NFCSR_NFCE1 (1 << 1)
#define EMC_NFCSR_NFCE1 (1 << 1)
#define EMC_NFCSR_NFE1 (1 << 0)
#define EMC_NFCSR_NFE(n) (1 << (((n)-1)*2))
#define EMC_NFCSR_NFCE(n) (1 << (((n)*2)-1))
/* NAND Flash ECC Control Register */
#define EMC_NFECR_PRDY (1 << 4) /* Parity Ready */

View file

@ -30,8 +30,10 @@
#include "storage.h"
#include "buffer.h"
#include "string.h"
#include "logf.h"
//#define USE_DMA
//#define USE_ECC
/*
* Standard NAND flash commands
@ -51,9 +53,9 @@
#define NAND_CMD_RESET 0xff
/* Extended commands for large page devices */
#define NAND_CMD_READSTART 0x30
#define NAND_CMD_RNDOUTSTART 0xE0
#define NAND_CMD_CACHEDPROG 0x15
#define NAND_CMD_READSTART 0x30
#define NAND_CMD_RNDOUTSTART 0xE0
#define NAND_CMD_CACHEDPROG 0x15
/* Status bits */
#define NAND_STATUS_FAIL 0x01
@ -69,8 +71,8 @@ struct nand_param
{
unsigned int bus_width; /* data bus width: 8-bit/16-bit */
unsigned int row_cycle; /* row address cycles: 2/3 */
unsigned int page_size; /* page size in bytes: 512/2048 */
unsigned int oob_size; /* oob size in bytes: 16/64 */
unsigned int page_size; /* page size in bytes: 512/2048/4096 */
unsigned int oob_size; /* oob size in bytes: 16/64/128 */
unsigned int page_per_block; /* pages per block: 32/64/128 */
};
@ -83,9 +85,9 @@ struct nand_param
*
*/
#define NAND_DATAPORT 0xb8000000
#define NAND_ADDRPORT 0xb8010000
#define NAND_COMMPORT 0xb8008000
#define NAND_DATAPORT 0xB8000000
#define NAND_ADDRPORT 0xB8010000
#define NAND_COMMPORT 0xB8008000
#define ECC_BLOCK 512
#define ECC_POS 6
@ -93,8 +95,8 @@ struct nand_param
#define __nand_cmd(n) (REG8(NAND_COMMPORT) = (n))
#define __nand_addr(n) (REG8(NAND_ADDRPORT) = (n))
#define __nand_data8() REG8(NAND_DATAPORT)
#define __nand_data16() REG16(NAND_DATAPORT)
#define __nand_data8() (REG8(NAND_DATAPORT))
#define __nand_data16() (REG16(NAND_DATAPORT))
#define __nand_enable() (REG_EMC_NFCSR |= EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1)
#define __nand_disable() (REG_EMC_NFCSR &= ~(EMC_NFCSR_NFCE1))
@ -118,17 +120,16 @@ static unsigned char temp_page[4096]; /* Max page size */
static inline void jz_nand_wait_ready(void)
{
unsigned int timeout = 1000;
register unsigned int timeout = 1000;
while ((REG_GPIO_PXPIN(2) & 0x40000000) && timeout--);
while (!(REG_GPIO_PXPIN(2) & 0x40000000));
}
#ifndef USE_DMA
static inline void jz_nand_read_buf16(void *buf, int count)
{
int i;
unsigned short *p = (unsigned short *)buf;
register int i;
register unsigned short *p = (unsigned short *)buf;
for (i = 0; i < count; i += 2)
*p++ = __nand_data16();
@ -136,15 +137,13 @@ static inline void jz_nand_read_buf16(void *buf, int count)
static inline void jz_nand_read_buf8(void *buf, int count)
{
int i;
unsigned char *p = (unsigned char *)buf;
register int i;
register unsigned char *p = (unsigned char *)buf;
for (i = 0; i < count; i++)
*p++ = __nand_data8();
}
#else
static void jz_nand_write_dma(void *source, unsigned int len, int bw)
{
mutex_lock(&nand_mtx);
@ -226,8 +225,7 @@ void DMA_CALLBACK(DMA_NAND_CHANNEL)(void)
wakeup_signal(&nand_wkup);
}
#endif
#endif /* USE_DMA */
static inline void jz_nand_read_buf(void *buf, int count, int bw)
{
@ -244,6 +242,7 @@ static inline void jz_nand_read_buf(void *buf, int count, int bw)
#endif
}
#ifdef USE_ECC
/*
* Correct 1~9-bit errors in 512-bytes data
*/
@ -258,7 +257,8 @@ static void jz_rs_correct(unsigned char *dat, int idx, int mask)
i = (j == 0) ? (i - 1) : i;
j = (j == 0) ? 7 : (j - 1);
if (i > 512) return;
if (i > 512)
return;
if (i == 512)
d = dat[i - 1];
@ -275,11 +275,12 @@ static void jz_rs_correct(unsigned char *dat, int idx, int mask)
if (i < 512)
dat[i] = (d >> 8) & 0xff;
}
#endif
/*
* Read oob
*/
static int jz_nand_read_oob(int page_addr, unsigned char *buf, int size)
static int jz_nand_read_oob(unsigned long page_addr, unsigned char *buf, int size)
{
struct nand_param *nandp = &internal_param;
int page_size, row_cycle, bus_width;
@ -335,14 +336,14 @@ static int jz_nand_read_oob(int page_addr, unsigned char *buf, int size)
* page - page number within a block: 0, 1, 2, ...
* dst - pointer to target buffer
*/
static int jz_nand_read_page(int block, int page, unsigned char *dst)
static int jz_nand_read_page(unsigned long page_addr, unsigned char *dst)
{
struct nand_param *nandp = &internal_param;
int page_size, oob_size, page_per_block;
int row_cycle, bus_width, ecc_count;
int page_addr, i, j;
int i, j;
unsigned char *data_buf;
unsigned char oob_buf[128];
unsigned char oob_buf[nandp->oob_size];
page_size = nandp->page_size;
oob_size = nandp->oob_size;
@ -350,8 +351,6 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
row_cycle = nandp->row_cycle;
bus_width = nandp->bus_width;
page_addr = page + block * page_per_block;
/*
* Read oob data
*/
@ -372,7 +371,7 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
/* Send page address */
__nand_addr(page_addr & 0xff);
__nand_addr((page_addr >> 8) & 0xff);
if (row_cycle == 3)
if (row_cycle >= 3)
__nand_addr((page_addr >> 16) & 0xff);
/* Send READSTART command for 2048 ps NAND */
@ -389,16 +388,19 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
for (i = 0; i < ecc_count; i++)
{
#ifdef USE_ECC
volatile unsigned char *paraddr = (volatile unsigned char *)EMC_NFPAR0;
unsigned int stat;
/* Enable RS decoding */
REG_EMC_NFINTS = 0x0;
__nand_ecc_rs_decoding();
#endif
/* Read data */
jz_nand_read_buf((void *)data_buf, ECC_BLOCK, bus_width);
#ifdef USE_ECC
/* Set PAR values */
for (j = 0; j < PAR_SIZE; j++)
*paraddr++ = oob_buf[ECC_POS + i*PAR_SIZE + j];
@ -420,7 +422,7 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
if (stat & EMC_NFINTS_UNCOR)
{
/* Uncorrectable error occurred */
panicf("Uncorrectable ECC error at NAND page 0x%x block 0x%x", page, block);
panicf("Uncorrectable ECC error at NAND page address 0x%lx", page_addr);
return -1;
}
else
@ -452,6 +454,7 @@ static int jz_nand_read_page(int block, int page, unsigned char *dst)
}
}
}
#endif
data_buf += ECC_BLOCK;
}
@ -502,7 +505,7 @@ static int jz_nand_init(void)
internal_param.bus_width = 8;
internal_param.row_cycle = chip_info->row_cycles;
internal_param.page_size = chip_info->page_size;
internal_param.oob_size = chip_info->page_size/32;
internal_param.oob_size = chip_info->spare_size;
internal_param.page_per_block = chip_info->pages_per_block;
return 0;
@ -532,21 +535,24 @@ int nand_read_sectors(IF_MV2(int drive,) unsigned long start, int count, void* b
{
int i, ret = 0;
logf("nand_read_sectors(%ld, %d, 0x%x)", start, count, (int)buf);
start *= 512;
count *= 512;
if(count <= chip_info->page_size)
{
ret = jz_nand_read_page(start % (chip_info->page_size * chip_info->pages_per_block), start % chip_info->page_size, temp_page);
memcpy(buf, temp_page, count);
ret = jz_nand_read_page(start/chip_info->page_size, temp_page);
memcpy(buf, temp_page+(start%chip_info->page_size), count);
return ret;
}
else
{
for(i=0; i<count && ret == 0; i+=chip_info->page_size)
for(i=0; i<count && ret==0; i+=chip_info->page_size)
{
ret = jz_nand_read_page((start+i) % (chip_info->page_size * chip_info->pages_per_block), (start+i) % chip_info->page_size, temp_page);
memcpy(buf+i, temp_page, (count-i < chip_info->page_size ? count-i : chip_info->page_size));
ret = jz_nand_read_page((start+i)/chip_info->page_size, temp_page);
memcpy(buf+i, temp_page+((start+i)%chip_info->page_size),
(count-i < chip_info->page_size ? count-i : chip_info->page_size));
}
return ret;
}
@ -607,7 +613,7 @@ void nand_get_info(IF_MV2(int drive,) struct storage_info *info)
/* blocks count */
/* TODO: proper amount of sectors! */
info->num_sectors = (chip_info->page_size / 512) * chip_info->pages_per_block * chip_info->blocks_per_bank;
info->num_sectors = ((chip_info->page_size+chip_info->spare_size) / 512) * chip_info->pages_per_block * chip_info->blocks_per_bank;
info->sector_size = 512;
}
#endif