diff options
-rw-r--r-- | drivers/mtd/nand/vf610_nfc.c | 67 | ||||
-rw-r--r-- | include/configs/colibri_vf.h | 1 | ||||
-rw-r--r-- | include/configs/vf610twr.h | 1 |
3 files changed, 51 insertions, 18 deletions
diff --git a/drivers/mtd/nand/vf610_nfc.c b/drivers/mtd/nand/vf610_nfc.c index 2c02ff5996..5c11ac94aa 100644 --- a/drivers/mtd/nand/vf610_nfc.c +++ b/drivers/mtd/nand/vf610_nfc.c @@ -62,6 +62,7 @@ * Briefly these are bitmasks of controller cycles. */ #define READ_PAGE_CMD_CODE 0x7EE0 +#define READ_ONFI_PARAM_CMD_CODE 0x4860 #define PROGRAM_PAGE_CMD_CODE 0x7FC0 #define ERASE_CMD_CODE 0x4EC0 #define READ_ID_CMD_CODE 0x4804 @@ -150,6 +151,7 @@ struct vf610_nfc { int alt_buf; #define ALT_BUF_ID 1 #define ALT_BUF_STAT 2 +#define ALT_BUF_ONFI 3 struct clk *clk; }; @@ -390,6 +392,16 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); break; + case NAND_CMD_PARAM: + nfc->alt_buf = ALT_BUF_ONFI; + vf610_nfc_transfer_size(nfc->regs, 768); + vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM, + READ_ONFI_PARAM_CMD_CODE); + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, + ROW_ADDR_SHIFT, column); + vf610_nfc_ecc_mode(mtd, ECC_BYPASS); + break; + case NAND_CMD_ERASE1: vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_commands(nfc->regs, command, @@ -399,8 +411,11 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, case NAND_CMD_READID: nfc->alt_buf = ALT_BUF_ID; + nfc->column = 0; vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE); + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK, + ROW_ADDR_SHIFT, column); break; case NAND_CMD_STATUS: @@ -422,17 +437,11 @@ static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) struct vf610_nfc *nfc = mtd_to_nfc(mtd); uint c = nfc->column; - switch (nfc->alt_buf) { - case ALT_BUF_ID: - *buf = vf610_nfc_get_id(mtd, c); - break; - case ALT_BUF_STAT: - *buf = vf610_nfc_get_status(mtd); - break; - default: - vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); - break; - } + /* Alternate buffers are only supported through read_byte */ + if (nfc->alt_buf) + return; + + vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len); nfc->column += len; } @@ -453,8 +462,29 @@ static void vf610_nfc_write_buf(struct mtd_info *mtd, const u_char *buf, /* Read byte from NFC buffers */ static u8 vf610_nfc_read_byte(struct mtd_info *mtd) { + struct vf610_nfc *nfc = mtd_to_nfc(mtd); u8 tmp; - vf610_nfc_read_buf(mtd, &tmp, sizeof(tmp)); + uint c = nfc->column; + + switch (nfc->alt_buf) { + case ALT_BUF_ID: + tmp = vf610_nfc_get_id(mtd, c); + break; + case ALT_BUF_STAT: + tmp = vf610_nfc_get_status(mtd); + break; + case ALT_BUF_ONFI: +#ifdef __LITTLE_ENDIAN + /* Reverse byte since the controller uses big endianness */ + c = nfc->column ^ 0x3; + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); + break; +#endif + default: + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c)); + break; + } + nfc->column++; return tmp; } @@ -602,13 +632,11 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) mtd->priv = chip; chip->priv = nfc; - if (cfg.width == 16) { + if (cfg.width == 16) chip->options |= NAND_BUSWIDTH_16; - vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); - } else { - chip->options &= ~NAND_BUSWIDTH_16; - vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); - } + + /* Use 8-bit mode during initialization */ + vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); /* Disable subpage writes as we do not provide ecc->hwctl */ chip->options |= NAND_NO_SUBPAGE_WRITE; @@ -651,6 +679,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) goto error; } + if (cfg.width == 16) + vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT); + chip->ecc.mode = NAND_ECC_SOFT; /* default */ /* Single buffer only, max 256 OOB minus ECC status */ diff --git a/include/configs/colibri_vf.h b/include/configs/colibri_vf.h index b3c73bbb96..804291dfaa 100644 --- a/include/configs/colibri_vf.h +++ b/include/configs/colibri_vf.h @@ -50,6 +50,7 @@ /* NAND support */ #define CONFIG_CMD_NAND +#define CONFIG_SYS_NAND_ONFI_DETECTION #define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR diff --git a/include/configs/vf610twr.h b/include/configs/vf610twr.h index 621aa13484..aa310411bf 100644 --- a/include/configs/vf610twr.h +++ b/include/configs/vf610twr.h @@ -48,6 +48,7 @@ /* NAND support */ #define CONFIG_CMD_NAND #define CONFIG_CMD_NAND_TRIMFFS +#define CONFIG_SYS_NAND_ONFI_DETECTION #ifdef CONFIG_CMD_NAND #define CONFIG_USE_ARCH_MEMCPY |