[PATCH 2/5] mtd: mxc_nand fixups
John Ogness
john.ogness at linutronix.de
Fri Jun 18 13:00:27 EDT 2010
This patch sets the NFC registers for spare size and pages per block.
For NFCv21 it also sets the ECC mode to 4-bit, since this driver only
supports up to 16 OOB bytes per 512 data bytes.
The patch is against linux-next 20100618.
Signed-off-by: John Ogness <john.ogness at linutronix.de>
---
drivers/mtd/nand/mxc_nand.c | 48 +++++++++++++++++++++++++++++++++-
1 file changed, 47 insertions(+), 1 deletion(-)
Index: linux-next-20100618/drivers/mtd/nand/mxc_nand.c
===================================================================
--- linux-next-20100618.orig/drivers/mtd/nand/mxc_nand.c
+++ linux-next-20100618/drivers/mtd/nand/mxc_nand.c
@@ -86,6 +86,7 @@
* Status operation */
#define NFC_INT 0x8000
+#define NFC_ECC_4BIT (1 << 0)
#define NFC_SP_EN (1 << 2)
#define NFC_ECC_EN (1 << 3)
#define NFC_INT_MSK (1 << 4)
@@ -94,6 +95,11 @@
#define NFC_CE (1 << 7)
#define NFC_ONE_CYCLE (1 << 8)
+#define NFC_PPB_SHIFT 9
+#define NFC_PPB_MASK (3 << NFC_PPB_SHIFT)
+
+#define NFC_RSLTSPARE_AREA_MASK 0xff
+
struct mxc_nand_host {
struct mtd_info mtd;
struct nand_chip nand;
@@ -557,21 +563,35 @@ static void preset(struct mtd_info *mtd)
struct mxc_nand_host *host = nand_chip->priv;
uint16_t tmp;
- /* enable interrupt, disable spare enable */
+ /* enable interrupt, disable spare enable, setup ECC */
tmp = readw(host->regs + NFC_CONFIG1);
tmp &= ~NFC_INT_MSK;
tmp &= ~NFC_SP_EN;
if (nand_chip->ecc.mode == NAND_ECC_HW) {
tmp |= NFC_ECC_EN;
+
+ if (nfc_is_v21()) {
+ /* use 4-bit ECC mode */
+ tmp |= NFC_ECC_4BIT;
+ }
} else {
tmp &= ~NFC_ECC_EN;
}
writew(tmp, host->regs + NFC_CONFIG1);
+
/* preset operation */
/* Unlock the internal RAM Buffer */
writew(0x2, host->regs + NFC_CONFIG);
+ if (nfc_is_v21()) {
+ /* configure spare size (in 16-bit blocks) */
+ tmp = readw(host->regs + NFC_RSLTSPARE_AREA);
+ tmp &= ~NFC_RSLTSPARE_AREA_MASK;
+ tmp |= host->spare_len / 2;
+ writew(tmp, host->regs + NFC_RSLTSPARE_AREA);
+ }
+
/* Blocks to be unlocked */
if (nfc_is_v21()) {
writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
@@ -817,6 +837,32 @@ static int __init mxcnd_probe(struct pla
goto escan;
}
+ if (nfc_is_v21()) {
+ /* setup PPB */
+
+ uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
+ uint16_t tmp;
+
+ tmp = readw(host->regs + NFC_CONFIG1);
+ tmp &= ~NFC_PPB_MASK;
+ switch (pages_per_block) {
+ case 32:
+ /* PPB set to 0 */
+ break;
+ case 64:
+ tmp |= 1 << NFC_PPB_SHIFT;
+ break;
+ case 256:
+ tmp |= 3 << NFC_PPB_SHIFT;
+ break;
+ default:
+ /* 128 (reset value) */
+ tmp |= 2 << NFC_PPB_SHIFT;
+ break;
+ }
+ writew(tmp, host->regs + NFC_CONFIG1);
+ }
+
if (mtd->writesize == 2048)
this->ecc.layout = oob_largepage;
More information about the linux-arm-kernel
mailing list