Skip to content
Snippets Groups Projects
Commit 8fca2d8c authored by Stefan Agner's avatar Stefan Agner Committed by Scott Wood
Browse files

mtd: vf610_nfc: enable ONFI detection


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: default avatarStefan Agner <stefan@agner.ch>
parent 080a71e8
No related branches found
No related tags found
No related merge requests found
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
* Briefly these are bitmasks of controller cycles. * Briefly these are bitmasks of controller cycles.
*/ */
#define READ_PAGE_CMD_CODE 0x7EE0 #define READ_PAGE_CMD_CODE 0x7EE0
#define READ_ONFI_PARAM_CMD_CODE 0x4860
#define PROGRAM_PAGE_CMD_CODE 0x7FC0 #define PROGRAM_PAGE_CMD_CODE 0x7FC0
#define ERASE_CMD_CODE 0x4EC0 #define ERASE_CMD_CODE 0x4EC0
#define READ_ID_CMD_CODE 0x4804 #define READ_ID_CMD_CODE 0x4804
...@@ -150,6 +151,7 @@ struct vf610_nfc { ...@@ -150,6 +151,7 @@ struct vf610_nfc {
int alt_buf; int alt_buf;
#define ALT_BUF_ID 1 #define ALT_BUF_ID 1
#define ALT_BUF_STAT 2 #define ALT_BUF_STAT 2
#define ALT_BUF_ONFI 3
struct clk *clk; struct clk *clk;
}; };
...@@ -390,6 +392,16 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, ...@@ -390,6 +392,16 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
vf610_nfc_ecc_mode(mtd, ECC_HW_MODE); vf610_nfc_ecc_mode(mtd, ECC_HW_MODE);
break; 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: case NAND_CMD_ERASE1:
vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_transfer_size(nfc->regs, 0);
vf610_nfc_send_commands(nfc->regs, command, vf610_nfc_send_commands(nfc->regs, command,
...@@ -399,8 +411,11 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command, ...@@ -399,8 +411,11 @@ static void vf610_nfc_command(struct mtd_info *mtd, unsigned command,
case NAND_CMD_READID: case NAND_CMD_READID:
nfc->alt_buf = ALT_BUF_ID; nfc->alt_buf = ALT_BUF_ID;
nfc->column = 0;
vf610_nfc_transfer_size(nfc->regs, 0); vf610_nfc_transfer_size(nfc->regs, 0);
vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE); 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; break;
case NAND_CMD_STATUS: case NAND_CMD_STATUS:
...@@ -422,17 +437,11 @@ static void vf610_nfc_read_buf(struct mtd_info *mtd, u_char *buf, int len) ...@@ -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); struct vf610_nfc *nfc = mtd_to_nfc(mtd);
uint c = nfc->column; uint c = nfc->column;
switch (nfc->alt_buf) { /* Alternate buffers are only supported through read_byte */
case ALT_BUF_ID: if (nfc->alt_buf)
*buf = vf610_nfc_get_id(mtd, c); return;
break;
case ALT_BUF_STAT: vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len);
*buf = vf610_nfc_get_status(mtd);
break;
default:
vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len);
break;
}
nfc->column += len; nfc->column += len;
} }
...@@ -453,8 +462,29 @@ static void vf610_nfc_write_buf(struct mtd_info *mtd, const u_char *buf, ...@@ -453,8 +462,29 @@ static void vf610_nfc_write_buf(struct mtd_info *mtd, const u_char *buf,
/* Read byte from NFC buffers */ /* Read byte from NFC buffers */
static u8 vf610_nfc_read_byte(struct mtd_info *mtd) static u8 vf610_nfc_read_byte(struct mtd_info *mtd)
{ {
struct vf610_nfc *nfc = mtd_to_nfc(mtd);
u8 tmp; 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; return tmp;
} }
...@@ -602,13 +632,11 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) ...@@ -602,13 +632,11 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
mtd->priv = chip; mtd->priv = chip;
chip->priv = nfc; chip->priv = nfc;
if (cfg.width == 16) { if (cfg.width == 16)
chip->options |= NAND_BUSWIDTH_16; chip->options |= NAND_BUSWIDTH_16;
vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
} else { /* Use 8-bit mode during initialization */
chip->options &= ~NAND_BUSWIDTH_16; vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
}
/* Disable subpage writes as we do not provide ecc->hwctl */ /* Disable subpage writes as we do not provide ecc->hwctl */
chip->options |= NAND_NO_SUBPAGE_WRITE; chip->options |= NAND_NO_SUBPAGE_WRITE;
...@@ -651,6 +679,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr) ...@@ -651,6 +679,9 @@ static int vf610_nfc_nand_init(int devnum, void __iomem *addr)
goto error; goto error;
} }
if (cfg.width == 16)
vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
chip->ecc.mode = NAND_ECC_SOFT; /* default */ chip->ecc.mode = NAND_ECC_SOFT; /* default */
/* Single buffer only, max 256 OOB minus ECC status */ /* Single buffer only, max 256 OOB minus ECC status */
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
/* NAND support */ /* NAND support */
#define CONFIG_CMD_NAND #define CONFIG_CMD_NAND
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_SYS_MAX_NAND_DEVICE 1 #define CONFIG_SYS_MAX_NAND_DEVICE 1
#define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
/* NAND support */ /* NAND support */
#define CONFIG_CMD_NAND #define CONFIG_CMD_NAND
#define CONFIG_CMD_NAND_TRIMFFS #define CONFIG_CMD_NAND_TRIMFFS
#define CONFIG_SYS_NAND_ONFI_DETECTION
#ifdef CONFIG_CMD_NAND #ifdef CONFIG_CMD_NAND
#define CONFIG_USE_ARCH_MEMCPY #define CONFIG_USE_ARCH_MEMCPY
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment