summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaurus Cuelenaere <mcuelenaere@gmail.com>2009-01-22 00:04:20 +0000
committerMaurus Cuelenaere <mcuelenaere@gmail.com>2009-01-22 00:04:20 +0000
commit311d2f12ed024cf11971f23231e05a0143361115 (patch)
tree3537e656cbb1a1e6bbba3a8431a34059cc8398b1
parente79fc8aaef541b48a84a23e6771e3ec5a2efe5ac (diff)
downloadrockbox-311d2f12ed024cf11971f23231e05a0143361115.zip
rockbox-311d2f12ed024cf11971f23231e05a0143361115.tar.gz
rockbox-311d2f12ed024cf11971f23231e05a0143361115.tar.bz2
rockbox-311d2f12ed024cf11971f23231e05a0143361115.tar.xz
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
-rw-r--r--firmware/drivers/nand_id.c32
-rw-r--r--firmware/export/jz4740.h10
-rw-r--r--firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c78
3 files changed, 66 insertions, 54 deletions
diff --git a/firmware/drivers/nand_id.c b/firmware/drivers/nand_id.c
index 4dc1ec1..dfb96c8 100644
--- a/firmware/drivers/nand_id.c
+++ b/firmware/drivers/nand_id.c
@@ -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;
diff --git a/firmware/export/jz4740.h b/firmware/export/jz4740.h
index aa31a22..7910fbe 100644
--- a/firmware/export/jz4740.h
+++ b/firmware/export/jz4740.h
@@ -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 */
diff --git a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
index 8c4ad40..851472b 100644
--- a/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
+++ b/firmware/target/mips/ingenic_jz47xx/ata-nand-jz4740.c
@@ -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