Commit 8fca2d8cb84fb039bb41061f5f5fd9f31cd596c9

Authored by Stefan Agner
Committed by Scott Wood
1 parent 080a71e8e9

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: Stefan Agner <stefan@agner.ch>

Showing 3 changed files with 51 additions and 18 deletions Side-by-side Diff

drivers/mtd/nand/vf610_nfc.c
... ... @@ -62,6 +62,7 @@
62 62 * Briefly these are bitmasks of controller cycles.
63 63 */
64 64 #define READ_PAGE_CMD_CODE 0x7EE0
  65 +#define READ_ONFI_PARAM_CMD_CODE 0x4860
65 66 #define PROGRAM_PAGE_CMD_CODE 0x7FC0
66 67 #define ERASE_CMD_CODE 0x4EC0
67 68 #define READ_ID_CMD_CODE 0x4804
... ... @@ -150,6 +151,7 @@
150 151 int alt_buf;
151 152 #define ALT_BUF_ID 1
152 153 #define ALT_BUF_STAT 2
  154 +#define ALT_BUF_ONFI 3
153 155 struct clk *clk;
154 156 };
155 157  
... ... @@ -390,6 +392,16 @@
390 392 vf610_nfc_ecc_mode(mtd, ECC_HW_MODE);
391 393 break;
392 394  
  395 + case NAND_CMD_PARAM:
  396 + nfc->alt_buf = ALT_BUF_ONFI;
  397 + vf610_nfc_transfer_size(nfc->regs, 768);
  398 + vf610_nfc_send_command(nfc->regs, NAND_CMD_PARAM,
  399 + READ_ONFI_PARAM_CMD_CODE);
  400 + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
  401 + ROW_ADDR_SHIFT, column);
  402 + vf610_nfc_ecc_mode(mtd, ECC_BYPASS);
  403 + break;
  404 +
393 405 case NAND_CMD_ERASE1:
394 406 vf610_nfc_transfer_size(nfc->regs, 0);
395 407 vf610_nfc_send_commands(nfc->regs, command,
396 408  
... ... @@ -399,8 +411,11 @@
399 411  
400 412 case NAND_CMD_READID:
401 413 nfc->alt_buf = ALT_BUF_ID;
  414 + nfc->column = 0;
402 415 vf610_nfc_transfer_size(nfc->regs, 0);
403 416 vf610_nfc_send_command(nfc->regs, command, READ_ID_CMD_CODE);
  417 + vf610_nfc_set_field(mtd, NFC_ROW_ADDR, ROW_ADDR_MASK,
  418 + ROW_ADDR_SHIFT, column);
404 419 break;
405 420  
406 421 case NAND_CMD_STATUS:
407 422  
... ... @@ -422,18 +437,12 @@
422 437 struct vf610_nfc *nfc = mtd_to_nfc(mtd);
423 438 uint c = nfc->column;
424 439  
425   - switch (nfc->alt_buf) {
426   - case ALT_BUF_ID:
427   - *buf = vf610_nfc_get_id(mtd, c);
428   - break;
429   - case ALT_BUF_STAT:
430   - *buf = vf610_nfc_get_status(mtd);
431   - break;
432   - default:
433   - vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len);
434   - break;
435   - }
  440 + /* Alternate buffers are only supported through read_byte */
  441 + if (nfc->alt_buf)
  442 + return;
436 443  
  444 + vf610_nfc_memcpy(buf, nfc->regs + NFC_MAIN_AREA(0) + c, len);
  445 +
437 446 nfc->column += len;
438 447 }
439 448  
440 449  
... ... @@ -453,8 +462,29 @@
453 462 /* Read byte from NFC buffers */
454 463 static u8 vf610_nfc_read_byte(struct mtd_info *mtd)
455 464 {
  465 + struct vf610_nfc *nfc = mtd_to_nfc(mtd);
456 466 u8 tmp;
457   - vf610_nfc_read_buf(mtd, &tmp, sizeof(tmp));
  467 + uint c = nfc->column;
  468 +
  469 + switch (nfc->alt_buf) {
  470 + case ALT_BUF_ID:
  471 + tmp = vf610_nfc_get_id(mtd, c);
  472 + break;
  473 + case ALT_BUF_STAT:
  474 + tmp = vf610_nfc_get_status(mtd);
  475 + break;
  476 + case ALT_BUF_ONFI:
  477 +#ifdef __LITTLE_ENDIAN
  478 + /* Reverse byte since the controller uses big endianness */
  479 + c = nfc->column ^ 0x3;
  480 + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c));
  481 + break;
  482 +#endif
  483 + default:
  484 + tmp = *((u8 *)(nfc->regs + NFC_MAIN_AREA(0) + c));
  485 + break;
  486 + }
  487 + nfc->column++;
458 488 return tmp;
459 489 }
460 490  
461 491  
462 492  
... ... @@ -602,14 +632,12 @@
602 632 mtd->priv = chip;
603 633 chip->priv = nfc;
604 634  
605   - if (cfg.width == 16) {
  635 + if (cfg.width == 16)
606 636 chip->options |= NAND_BUSWIDTH_16;
607   - vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
608   - } else {
609   - chip->options &= ~NAND_BUSWIDTH_16;
610   - vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
611   - }
612 637  
  638 + /* Use 8-bit mode during initialization */
  639 + vf610_nfc_clear(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
  640 +
613 641 /* Disable subpage writes as we do not provide ecc->hwctl */
614 642 chip->options |= NAND_NO_SUBPAGE_WRITE;
615 643  
... ... @@ -650,6 +678,9 @@
650 678 err = -ENXIO;
651 679 goto error;
652 680 }
  681 +
  682 + if (cfg.width == 16)
  683 + vf610_nfc_set(mtd, NFC_FLASH_CONFIG, CONFIG_16BIT);
653 684  
654 685 chip->ecc.mode = NAND_ECC_SOFT; /* default */
655 686  
include/configs/colibri_vf.h
... ... @@ -50,6 +50,7 @@
50 50  
51 51 /* NAND support */
52 52 #define CONFIG_CMD_NAND
  53 +#define CONFIG_SYS_NAND_ONFI_DETECTION
53 54 #define CONFIG_SYS_MAX_NAND_DEVICE 1
54 55 #define CONFIG_SYS_NAND_BASE NFC_BASE_ADDR
55 56  
include/configs/vf610twr.h
... ... @@ -48,6 +48,7 @@
48 48 /* NAND support */
49 49 #define CONFIG_CMD_NAND
50 50 #define CONFIG_CMD_NAND_TRIMFFS
  51 +#define CONFIG_SYS_NAND_ONFI_DETECTION
51 52  
52 53 #ifdef CONFIG_CMD_NAND
53 54 #define CONFIG_USE_ARCH_MEMCPY