[U-Boot] [PATCH v3 8/8] mtd: vf610_nfc: enable ONFI detection
Stefan Agner
stefan at agner.ch
Fri May 8 19:07:13 CEST 2015
This changes enable ONFI detection. The Read ID command now allows
one address byte which is needed for ONFI detection. To read the
ONFI parameter page, the NAND_CMD_PARAM need to be supported. The
CMD code enables one command and one address byte along with reading
data from flash using R/B#, as specified by ONFI.
Signed-off-by: Stefan Agner <stefan at agner.ch>
---
drivers/mtd/nand/vf610_nfc.c | 67 ++++++++++++++++++++++++++++++++------------
include/configs/colibri_vf.h | 1 +
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 2c02ff5..5c11ac9 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 b3c73bb..804291d 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 621aa13..aa31041 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
--
2.3.7
More information about the U-Boot
mailing list